2010-11-24 73 views
3

我有一個.h文件中,除其他事項外,這種格式包含數據腳本從一個源數據遷移到另一個

struct X[]{ 
{"Field", "value1 value2 value"}, 
{"Field2", "value11 value12 value232"}, 
{"Field3", "x y z"}, 
{"Field4", "a bbb s"}, 
{"Field5", "sfsd sdfdsf sdfs"}; 
/****************/ 
}; 

我有文本文件,其中包含,我想在.H替換值具有新值的文件

value1 Valuesdfdsf1 
value2 Value1dfsdf 
value3 Value1_another 
sfsd  sfsd_ewew 
sdfdsf sdfdsf_ew 
sdfs  sfsd_new 

而生成的.h文件將包含上述文本文件中的替換項。其他一切都保持不變。

struct X[]{ 
    {"Field1", "value11 value12 value232"}, 
    {"Field2", "value11 value12 value232"}, 
    {"Field3", "x y z"}, 
    {"Field4", "a bbb s"}, 
    {"Field5", "sfsd_ewew sdfdsf_ew sdfs_new"}; 
    /****************/ 
    }; 

請幫我拿出一個解決方案使用的Unix工具來完成它:awk的,perl的,bash中,sed的,等

+0

字段值對總是在同一行上,值之間用單個空格分隔嗎? – DVK 2010-11-24 20:42:33

+0

空格/製表符,至少有一個空格是肯定的 – vehomzzz 2010-11-24 20:51:18

+0

不應將value2從第一行替換爲Value1dfsdf ? – DVK 2010-11-24 20:52:13

回答

0

這個腳本應該工作
KEYVAL是包含鍵值對
filetoreplace被修改包含數據的文件的文件
名爲文件改變將包含更改

#!/bin/sh 
echo 

keylist=`cat keyval | awk '{ print $1}'` 


while read line 
do 

for i in $keylist 
do 


if echo $line | grep -wq $i; then 

    value=`grep -w $i keyval | awk '{print $2}'` 
    line=`echo $line | sed -e "s/$i/$value/g"` 
fi 

done 

echo $line >> changed 

done < filetoreplace 
3
cat junk/n2.txt | perl -e '{use File::Slurp; my @r = File::Slurp::read_file("junk/n.txt"); my %r = map {chomp; (split(/\s+/,$_))[0,1]} @r; while (<>) { unless (/^\s*{"/) {print $_; next;}; my ($pre,$values,$post) = ($_ =~ /^(\s*{"[^"]+", ")([^"]+)(".*)$/); my @new_values = map { exists $r{$_} ? $r{$_}:$_ } split(/\s+/,$values); print $pre . join(" ",@new_values) . $post . "\n"; }}'  

結果:

struct X[]{ 
{"Field", "value1 Value1dfsdf value"}, 
{"Field2", "value11 value12 value232"}, 
{"Field3", "x y z"}, 
{"Field4", "a bbb s"}, 
{"Field5", "sfsd_ewew sdfdsf_ew sfsd_new"}; 
/****************/ 
}; 

代碼解開:

use File::Slurp; 
my @replacements = File::Slurp::read_file("junk/n.txt"); 
my %r = map {chomp; (split(/\s+/,$_))[0,1]} @replacements; 
while (<>) { 
    unless (/^\s*{"/) {print $_; next;} 
    my ($pre,$values,$post) = ($_ =~ /^(\s*{"[^"]+", ")([^"]+)(".*)$/); 
    my @new_values = map { exists $r{$_} ? $r{$_} : $_ } split(/\s+/, $values); 
    print $pre . join(" ",@new_values) . $post . "\n"; 
} 
2
#!/usr/bin/perl 

use strict; use warnings; 

# you need to populate %lookup from the text file 
my %lookup = qw(
    value1 Valuesdfdsf1 
    value2 Value1dfsdf 
    value3 Value1_another 
    sfsd  sfsd_ewew 
    sdfdsf sdfdsf_ew 
    sdfs  sfsd_new 
); 

while (my $line = <DATA>) { 
    if ($line =~ /^struct \w+\Q[]/) { 
     print $line; 
     process_struct(\*DATA, \%lookup); 
    } 
    else { 
     print $line; 
    } 
} 

sub process_struct { 
    my ($fh, $lookup) = @_; 

    while (my $line = <$fh>) { 
     unless ($line =~ /^{"(\w+)", "([^"]+)"}([,;])\s+/) { 
      print $line; 
      return; 
     } 
     my ($f, $v, $p) = ($1, $2, $3); 
     $v =~ s/(\w+)/exists $lookup->{$1} ? $lookup->{$1} : $1/eg; 
     printf qq|{"%s", "%s"}%s\n|, $f, $v, $p; 
    } 
    return; 
} 

__DATA__ 
struct X[]{ 
{"Field", "value1 value2 value"}, 
{"Field2", "value11 value12 value232"}, 
{"Field3", "x y z"}, 
{"Field4", "a bbb s"}, 
{"Field5", "sfsd sdfdsf sdfs"}; 
/****************/ 
}; 
1

這裏有一個簡單的尋找程序:

use strict; 
use warnings; 
use File::Copy; 

use constant { 
    OLD_HEADER_FILE => "headerfile.h", 
    NEW_HEADER_FILE => "newheaderfile.h", 
    DATA_TEXT_FILE => "data.txt", 
}; 

open (HEADER, "<", OLD_HEADER_FILE) or 
die qq(Can't open file old header file ") . OLD_HEADER_FILE . qq(" for reading); 

open (NEWHEADER, ">", NEW_HEADER_FILE) or 
die qq(Can't open file new header file ") . NEW_HEADER_FILE . qq(" for writing); 

open (DATA, "<", DATA_TEXT_FILE) or 
die qq(Can't open file data file ") . DATA_TEXT_FILE . qq(" for reading); 

# 
# Put Replacement Data in a Hash 
# 

my %dataHash; 
while (my $line = <DATA>) { 
    chomp($line); 
    my ($key, $value) = split (/\s+/, $line); 
    $dataHash{$key} = $value if ($key and $value); 
} 
close (DATA); 

# 
# NOW PARSE THOUGH HEADER 
# 

while (my $line = <HEADER>) { 
    chomp($line); 
    if ($line =~ /^\s*\{"Field/) { 
     foreach my $key (keys(%dataHash)) { 
      $line =~ s/\b$key\b/$dataHash{$key}/g; 
     } 
    } 
    print NEWHEADER "$line\n"; 
} 

close (HEADER); 
close (NEWHEADER); 
copy(NEW_HEADER_FILE, OLD_HEADER_FILE) or 
    die qq(Unable to replace ") . OLD_HEADER_FILE . qq(" with ") . NEW_HEADER_FILE . qq("); 

我可以使它更有效地通過使用map,但是這使得它更難理解。

基本上是:

  • 我打開三個文件,原來的標題,新的頭我建立和數據文件
  • 我第一次把我的數據放入其中替換文本鍵入散列由原文。 (如果我想要的話可​​以用相反的方法做到這一點
  • 然後,我會經過原始標題的每一行 **如果我看到一條看起來像它的字段行,我知道我可能不得不做了更換。 **對於我%dataHash每個條目,我做$key$dataHash{$key}替換值的置換。我用\b標記字boundries。這樣一來,field11不是取代的,因爲我看到field1在那個字符串 **現在我把這行寫回到我的新頭文件中,如果我沒有替換任何東西,我只寫回原始的行
  • 一旦我完成後,我將新的標題複製到舊的標題文件中。
0

如果您的文件很大,這可能會很慢。

gawk -F '[ \t]*|"' 'FNR == NR {repl[$1]=$2;next}{for (f=1;f<=NF;++f) for (r in repl) if ($f == r) $f=repl[r]; print} ' keyfile file.h 
相關問題