我正在尝试将一个新文件与一个旧文件合并。
主列上有一个唯一键,然后是一个分隔符"="和一个值。
- 如果两个文件中都存在主键,我必须保留旧值,如果新值不同,则在行附近添加注释
- 如果主键只存在于旧的中,请保留它
- 如果主键只存在于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。
谢谢你的帮助:)
编辑:
我在第一篇文章中没有准确指出,如果新的评论没有出现在前一个文件中,就必须保留。
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 = $valuen";
if ($new{$key}{value} ne $value) {
print ";new value:n";
print "; $key = $new{$key}{value}n";
}
} else {
print "$key = $valuen";
}
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