类似于我的老问题: 如何合并FileA.txt和FileB.txt给FileB.txt覆盖权力使用bash脚本?
我想合并两个configuration值文件,我也有fileA和fileB。 我希望fileA中的所有行都在fileA中,如果两个文件中都出现相同的configuration键,我希望fileB中的值覆盖fileA中的值。
每行总是以'config'开始,然后是一个键,最后是一个值。 难以实现的部分是,该值可以是带空格的引号string来分隔多个值(请参阅“网站”值)。
我已经有了一些使用awk的经验和一些bash的经验,但是我不能为了我的生活找出一个办法来做到这一点。 所有的帮助表示赞赏。 谢谢
的fileA:
config lanIP 10.1.1.1 config wanIP 1.1.1.1 config wanIPMask 255.255.255.255 config website "http://google.com http://yahoo.com"
FILEB:
config lanIP 192.168.1.1 config wanIP 1.1.1.1 config website "http://google.com http://yahoo.com" config moreWebsite "http://google.com http://msn.com"
预期产出:
config lanIP 192.168.1.1 config wanIP 1.1.1.1 config wanIPMask 255.255.255.255 config website "http://google.com http://yahoo.com" config moreWebsite "http://google.com http://msn.com"
这一行可能有助于:
awk '{a[$2]=$0}END{for(x in a)print a[x]}' fileA fileB
注意 :上面的行很短,但不保留行的顺序。 (你没有提到排序标准)
测试:
kent$ head ab ==> a <== config lanIP 10.1.1.1 config wanIP 1.1.1.1 config wanIPMask 255.255.255.255 config website "http://google.com http://yahoo.com" ==> b <== config lanIP 192.168.1.1 config wanIP 1.1.1.1 config website "http://google.com http://yahoo.com" config moreWebsite "http://google.com http://msn.com" kent$ awk '{a[$2]=$0}END{for(x in a)print a[x]}' ab config wanIP 1.1.1.1 config lanIP 192.168.1.1 config moreWebsite "http://google.com http://msn.com" config wanIPMask 255.255.255.255 config website "http://google.com http://yahoo.com"
如果你想在你的问题中有相同的顺序,请尝试下面的这一行:
awk '!($2 in a){i[NR]=$2}{a[$2]=$0}END{for(x=1;x<=NR;x++)if(x in i)print a[i[x]]}' ab
测试
kent$ awk '!($2 in a){i[NR]=$2}{a[$2]=$0}END{for(x=1;x<=NR;x++)if(x in i)print a[i[x]]}' ab config lanIP 192.168.1.1 config wanIP 1.1.1.1 config wanIPMask 255.255.255.255 config website "http://google.com http://yahoo.com" config moreWebsite "http://google.com http://msn.com"
如果你不介意使用Python这里是一个小脚本做你想做的。 把它翻译成awk应该很简单。 总体思路是,按顺序处理文件并填充字典,稍后处理的文件中的值将覆盖先前处理的文件中的值:
import sys options = {} for fileName in sys.argv[1:]: with open(fileName) as f: for line in f: parts = line.strip().split(' ', 2) if len(parts) == 3: options[parts[1]] = parts[2] for k in options: print 'config', k, options[k]
你可以这样调用脚本:
python merge.py fileA fileB
Perl解决方案:
#!/usr/bin/perl use warnings; use strict; sub get_key_value { my $line = shift; die "Invalid line $line" unless $line =~ /^config /; chomp $line; return (split / /, $line, 3)[1, 2]; } my %result; open my $MINOR, '<', 'fileA' or die "Cannot open fileA: $!"; while (<$MINOR>) { my ($key, $value) = get_key_value($_); $result{$key} = $value; } open my $MAJOR, '<', 'fileB' or die "Cannot open fileB: $!"; while (<$MAJOR>) { my ($key, $value) = get_key_value($_); delete $result{$key}; print "config $key $value\n"; } for my $rest (keys %result) { print "config $rest $result{$rest}\n"; }