以下のように結合したい2つのファイルがあります。ファイル1:
AAA
1234
BBB
2341
ファイル 2:
AAA
9876
67 89 01
BBB
4567
23 45 23
最終ファイルが必要
AAA 1234 9876 67 89 01
BBB 2341 4567 23 45 23
awk、sed、またはその両方でこれを達成するにはどうすればよいですか?
純粋な awk:
/^[A-Z]/ {
token=$1
}
/^[0-9]/{
for (i=1; i<=NF; i++) {
C[token]=C[token] " " $i
}
}
END {
for (i in C) {
print i, C[i]
}
}
出力:
$ awk -f f.awk f1 f2
AAA 1234 9876 67 89 01
BBB 2341 4567 23 45 23
3 ライナーに短縮できます。
/^[A-Z]/ { token=$1 }
/^[0-9]/ { C[token]=C[token] " " $0 }
END { for (i in C) { print i, C[i] } }
これを試すことができます(おそらくそれは大きな解決策ですが、うまくいきます):
a.awk:
function print_stuff( start_string, end_string, file2 )
{
printf "%s ", start_string
getline
while ( $0 != end_string )
{
for ( i = 1; i < NF + 1; i++ )
{
printf "%s ", $i
}
if ( getline <= 0 )
{
break
}
}
while ( $0 != start_string )
{
if ( ( getline < file2 ) <= 0 )
{
break
}
}
getline < file2
while ( $0 != end_string )
{
for ( i = 1; i < NF + 1; i++ )
{
printf "%s ", $i
}
if ( ( getline < file2 ) <= 0 )
{
break
}
}
printf "\n"
close( file2 )
}
BEGIN { file2 = "file2"; aaa = "AAA"; bbb = "BBB" }
aaa { print_stuff( aaa, bbb, file2 ) }
bbb { print_stuff( bbb, "", file2 ) }
実行: awk -f a.awk file1
出力:
AAA 1234 9876 67 89 01
BBB 2341 4567 23 45 23
transform.awk
{key=($1 ~/[A-Z]+/)}
key==1 {
if(NR>1) {printf "\n"}
printf "%s",$1}
key==0 {printf " %s",$0}
END {printf "\n"}
これにより、固定数のエントリを想定せずにファイルが変換されますが、キーは最初の行の正規表現で指定された特定のパターンを確認します。この場合、一連の大文字。
join <(awk -F transform.awk file1) <(awk -F transform.awk file2)