3

以前の質問と同様に、 FileA.txtとFileB.txtをマージして、bashスクリプトを使用してFileB.txtに上書き権限を与えるにはどうすればよいですか?

2つの構成値ファイルをマージしたいのですが、ここでもfileAとfileBがあります。fileAのfileBのすべての行が必要です。両方のファイルに同じ構成キーが表示されている場合は、fileBの値がfileAの値を上書きするようにします。

各行は常に「config」で始まり、次にキーがあり、最後に値があります。難しいのは、値をスペースバー付きの引用符で囲まれた文字列にして、複数の値を区切ることができることです(「Webサイト」の値を参照)。

私は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"
4

3 に答える 3

5

このワンライナーは役立つかもしれません:

awk '{a[$2]=$0}END{for(x in a)print a[x]}' fileA fileB

:上の行は短いですが、行の順序は保持されません。(ソート基準については言及していません)

テスト:

kent$  head a b
==> 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]}' a b                       
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]]}' a b

テスト

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]]}' a b
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"
于 2012-11-14T09:40:17.767 に答える
0

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
于 2012-11-14T09:35:59.690 に答える
0

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";
}
于 2012-11-14T09:39:47.420 に答える