【问题标题】:awk two files based on 1st & 2nd columnawk 基于第一列和第二列的两个文件
【发布时间】:2014-05-24 03:27:00
【问题描述】:

我正在尝试将新文件与旧文件合并。

主列上有一个唯一键,然后是分隔符“=”和一个值。

  • 如果两个文件中都存在主键,我必须保留旧值,如果新值不同,请在该行附近添加注释。
  • 如果主键只存在于旧的,请保留它。
  • 如果主键只存在于new中,插入它

例如:

在旧文件中:

$ cat oldfile.txt
VAR NAME ONE = FOO
TWO BAR = VALUE 
; this is a comment

在新的:

$ cat newfile.txt
TWO BAR = VALUE
; this is a comment
VAR NAME ONE = BAR
NEW = DATA

期望的输出:

$ cat output.txt
VAR NAME ONE = FOO
;new value:
; VAR NAME ONE = BAR
TWO BAR = VALUE 
; this is a comment
NEW = DATA

我尝试处理 diff,但它只能逐行工作,我很确定 awk 可以做到。但我不是 awk 专家。我可以在 ksh 中写一些东西来完成这项工作,但我很确定还有另一种更快更简单的方法。

请注意,以前文件和新文件中的行顺序可能会改变,而且我使用的是 AIX (Unix),而不是 Linux。

感谢您的帮助:)

编辑:

我在第一篇文章中没有准确,如果之前的文件中没有新的 cmets,则必须保留它们。

【问题讨论】:

    标签: perl shell unix awk ksh


    【解决方案1】:

    Perl 解决方案。首先,它将新文件读入散列。然后它会遍历旧的并咨询哈希以进行更改。您没有在新文件中指定如何处理 cmets,您必须在相应的注释处调整代码。

    #!/usr/bin/perl
    use warnings;
    use strict;
    
    my ($oldfile, $newfile) = @ARGV;
    
    my %new;
    my $last;
    open my $NEW, '<', $newfile or die $!;
    while (<$NEW>) {
        chomp;
        if (/^;/) {
            $new{$last}{comment} = $_; # What should we do with comments?
        } elsif (! /=/) {
            warn "Invalid new line $.\n";
        } else {
            my ($key, $value) = split /\s* = \s*/x, $_, 2;
            $new{$key}{value} = $value;
            $last = $key;
        }
    }
    
    open my $OLD, '<', $oldfile or die $!;
    while (<$OLD>) {
        chomp;
        if (/^;/) {
            print "$_\n";
        } elsif (my ($key, $value) = split /\s* = \s*/x, $_, 2) {
            if (exists $new{$key}) {
                print "$key = $value\n";
                if ($new{$key}{value} ne $value) {
                    print ";new value:\n";
                    print "; $key = $new{$key}{value}\n";
                }
            } else {
                print "$key = $value\n";
            }
            delete $new{$key};
        } else {
            warn "Invalid old line $.\n";
        }
    }
    for my $key (keys %new) {
        print "$key = $new{$key}{value}\n";
    }
    

    【讨论】:

      【解决方案2】:

      使用awk

      awk '
      BEGIN {FS=OFS="="}
      NR==FNR {
           line[$1] = $2;
           next
      }
      ($1 in line) && ($2!=line[$1]) {
          print $0; 
          print ";new value:"; 
          print "; "$1, line[$1];
          delete line[$1]; 
          next
      }
      ($1 in line) && ($2==line[$1]) {
          print $0;
          delete line[$1]; 
          next
      }1
      END {
          for (k in line) 
              print k, line[k]
      }' newfile oldfile
      

      输出:

      VAR NAME ONE = FOO
      ;new value:
      ; VAR NAME ONE = BAR
      TWO BAR = VALUE
      ; this is a comment
      NEW = DATA
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-04
        • 1970-01-01
        • 1970-01-01
        • 2013-03-21
        • 1970-01-01
        • 2021-01-08
        相关资源
        最近更新 更多