代码之家  ›  专栏  ›  技术社区  ›  vehomzzz

用于将数据从一个源迁移到另一个源的脚本

  •  3
  • vehomzzz  · 技术社区  · 14 年前

    我有一个.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等

    5 回复  |  直到 9 年前
        1
  •  0
  •   Ankur Agarwal    14 年前

    这个脚本应该有效
    凯瓦尔 文件是否包含键值对?
    文件替换 文件是否包含要修改的数据?
    文件名为 改变 将包含更改

    #!/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
    
        2
  •  3
  •   DVK    14 年前
    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";
    }
    
        3
  •  2
  •   Sinan Ünür    14 年前
    #!/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"};
    /****************/
    };
    
        4
  •  1
  •   David W.    14 年前

    下面是一个简单的程序:

    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 在那根绳子里。 **现在我将行写回新的头文件。如果我没有替换任何东西,我只需写回原始行。
    • 完成后,我将新头文件复制到旧头文件上。
        5
  •  0
  •   Dennis Williamson    14 年前

    如果您的文件很大,这可能有点慢。

    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