次のパターンのリストを含むCSVファイルがあります。
ファイル1:
aaa;bbb
ccc;ddd
eee;fff
...
ファイル2:
aaa2222222222222222
3333333333333333333
4444444444444444444
bbb555555555555555
8888888888888888888
ccc5555555555555555
5555555555555555555
0000000000000000000
ddd6666666666666666
コマンド内のファイル1の各行に2つのパターン(例:&)を使用して、ファイル2の一致するパターン間の行を一致させ、印刷して出力を保存し、コマンドを次のパターンのペアに置き換えて繰り返すにはどうすればよいですか。aaa
?プロセス?bbb
sed -n '/aaa/,/bbb/p'
私の予想結果は
333333333333333
444444444444444
aaa
&の間に行があるので、新しいファイルに保存します。bbb
ccc
ddd
次に、ループを使用して&などの間の次の行セットを見つけます。
答え1
file1 または file2 に指定された重複またはネストされた範囲、または繰り返される開始/終了文字列がないと仮定すると、これはおそらくあなたが探しているものです。
$ cat tst.awk
BEGIN { FS=";" }
NR==FNR {
begs2ends[$1] = $2
next
}
end == "" {
for ( beg in begs2ends ) {
if ( index($0,beg) == 1 ) {
end = begs2ends[beg]
close(out)
out = "out" (++cnt) ".txt"
break
}
}
next
}
{
if ( index($0,end) == 1 ) {
end = ""
}
else {
print $0 " > " out
}
}
。
$ awk -f tst.awk file1 file2
3333333333333333333 > out1.txt
4444444444444444444 > out1.txt
5555555555555555555 > out2.txt
0000000000000000000 > out2.txt
初期テストが完了したら、print $0 " > " out
実際に別の出力ファイルを生成するように変更します。print > out
答え2
私は1つのプロセスしか必要ないのでawkが好きです。 sedを使用するには、非効率的なシェルループと複数のsedコマンドが必要になることがあります。
awk -F ';' '
NR==FNR{ #For the first file given as an argument
k++ #Increment k
pat1[k]=$1 #Add 1st field (before ;) to pat1 array
pat2[k]=$2 #Add 2nd field (after ;) to pat2 array
next #Start new cycle with the next line
}
{
for (i=1;i<=k;i++){
if ($0~pat2[i]){flag[i]=0} #If line has terminating pattern
if (flag[i]){print>(pat1[i]pat2[i])} #If flag=1, print this line to a file
if ($0~pat1[i]){flag[i]=1} #If line has starting pattern
}
}
' patterns.csv input
パラメータを逆に変更しないように注意してください。まずスキーマファイル、それから入力ファイルです。
入力例:
aaa2
3333
4444
bbb5
8888
ccc5
0000
aaa7
7777
bbb7
ddd6
次の内容で2つのファイルを作成します。
$ cat aaabbb
3333
4444
7777
$ cat cccddd
0000
aaa7
7777
bbb7
答え3
Gnu sedを使用してfile1の内容からsedコードを動的に準備し、生成されたコードをfile2に適用します。これらのファイルは自動的に生成されます。
sed -Ee 's|;|/,/|' \
-e 's|(.).*(.)|/&/{\n\t//!w FILE_\1\2\n}|' file1 \
| sed -nf - file2
more FILE_??
答え4
file2content="$( < file2 )";
while read p;do
((${#p}))&&sed -n "/${p%;*}/,/${p##*;}/p" <<< "${file2content}"|grep -v "^${p%;*}\|^${p##*;}" > "${p%;*}_${p##*;}";
done <file1