2010-11-24 70 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 
相关问题