入力内容:
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: org-abc
objectClass: org-xyz
objectClass: top
objectClass: inetOrgPerson
objectClass: org-abc
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: org-abc
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-xyz
objectClass: top
objectClass: inetOrgPerson
objectClass: org-xyz
objectClass: organizationalPerson
objectClass: person
50MB サイズの LDIF ファイルを読み込みます。
2つの改行の間の内容は、次のように処理されます。詰まった。
- この2行(objectClass:org-abc&objectClass:org-xyz)がランダムな順序で表示される場合詰まった次に、BLOCKからこれら2行を削除し、「objectClass:org-111」という新しい行を追加します。
(または)
- "objectClass: org-abc" 行が単独で存在する場合詰まったその行を「objectClass:org-222」に置き換えます。
(または)
- "objectClass: org-xyz" 行が単独で存在する場合詰まったその行を「objectClass:org-333」に置き換えます。
予想出力:
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: org-111
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-222
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-111
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-333
Linuxコマンド(sedまたはawk)を使用してこれらの出力を取得したり、より良い方法を提案したりするにはどうすればよいですか?
答え1
複雑AWK
解決策:
awk 'function process(a,c) { # process the lines of one passed block
for (i=1; i<=c; i++) {
split(a[i], fields); # split the line into 2 fields
if (fields[2]=="org-abc") abc="222";
else if (fields[2]=="org-xyz") xyz="333";
else print a[i]
}
if (abc || xyz) printf "objectClass: org-%s\n",(abc && xyz? "111" : (abc? "222":"333"))
}
!NF{ process(a, c); c=abc=xyz=0 }
{ a[++c]=$0 }
END{ process(a, c) }' file
これはメモリ適切配列がa
単一行を保持するため、ソリューション詰まった全体の処理時間中のみ。 (カウンターはc
次回毎回リセットされます。詰まった)
出力:
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: org-111
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-222
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-111
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-333
答え2
これはPerlの「短絡モード」()の一般的なユースケースです。-00
ここで、「行」は次のように定義され、\n\n
各段落が1行と見なされます。
$ perl -00 -lpe 'if(/: org-abc/ && /: org-xyz/){
s/(^|\n)[^\n]+: (org-abc|org-xyz)\s*(?=$|\n)//g;
s/$/\nobjectClass: org-111/;
}
else{
s/objectClass: org-abc/objectClass: org-222/;
s/objectClass: org-xyz/objectClass: org-333/
}' file
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: org-111
objectClass: top
objectClass: inetOrgPerson
objectClass: org-222
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-111
objectClass: top
objectClass: inetOrgPerson
objectClass: org-333
objectClass: organizationalPerson
objectClass: person
明確にするために、以下はスクリプトで圧縮されていない同じコンテンツです。
#!/usr/bin/env perl
## Paragraph mode
local $/="\n\n";
my $pat1 = 'objectClass: org-abc';
my $pat2 = 'objectClass: org-xyz';
## Read input file
while (my $line = <>) {
## Remove trailing newlines
chomp($line);
if($line =~ /$pat1/ && $line=~ /$pat2/){
$line =~ s/(^|\n)($pat1|pat2)\s*(?=$|\n)//g;
$line =~ s/$/\nobjectClass: org-111/;
}
else{
$line =~ s/$pat1/objectClass: org-222/;
$line =~ s/$pat2/objectClass: org-333/
}
print "$line\n\n";
}
答え3
また簡単ですsed
:
sed '/^$/!{H;1h;$!d;};x
/objectClass: org-abc/!{s/\(objectClass: org-\)xyz/\1333/;p;d;}
s/\(objectClass: org-\)xyz/\1111/;t1
s/\(objectClass: org-\)abc/\1222/;:b
:1
s/\nobjectClass: org-abc//'
最初の行はパターン空間からチャンクを収集し、残りの部分に対して確実な交換を行います。