繁体   English   中英

基于第一列和第二列awk两个文件

[英]awk two files based on 1st & 2nd column

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

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

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

例如:

在旧文件中:

$ 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。

谢谢你的帮助 :)

编辑:

我在第一篇文章中没有明确指出,如果以前的文件中还没有出现新的评论,则必须保留它们。

Perl解决方案。 首先,它将新文件读入哈希。 然后它遍历旧的,并查询哈希以获取更改。 您没有在新文件中指定处理注释的方法,必须在相应注释处调整代码。

#!/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";
}

使用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM