各行にフォーマットがあり、「単語」で昇順にソートされたテキスト ファイルがありますword @@@ type @@@ sentence
。ただし、一部の行は一意ではなく、前の行と同じ単語で始まっています。たとえば、以下の word1 を参照してください。
...
word0 @@@ type2 @@@ sentence0
word1 @@@ type1 @@@ sentence1
word1 @@@ type1 @@@ sentence2
word1 @@@ type1 @@@ sentence3
word1 @@@ type2 @@@ sentence4
word2 @@@ type1 @@@ sentence5
...
同じ単語とタイプの組み合わせを持つ行を、文を追加して 1 つに結合したいので、ファイルは次のようになります。
...
word0 @@@ type2 @@@ sentence0
word1 @@@ type1 @@@ sentence1 ;;; sentence2 ;;; sentence3
word1 @@@ type2 @@@ sentence4
word2 @@@ type1 @@@ sentence5
...
単語フィールドとタイプフィールドには空白がありません。
答え1
投稿されたサンプル入力に示されているように、入力がword
とフィールドの両方でソートされていると仮定します。type
$ cat tst.awk
BEGIN { FS=" @@@ "; ORS="" }
{ curr = $1 FS $2 }
curr != prev {
printf "%s%s", ORS, $0
prev = curr
ORS = RS
next
}
{ printf " ;;; %s", $NF }
END { print "" }
$ awk -f tst.awk file
word0 @@@ type2 @@@ sentence0
word1 @@@ type1 @@@ sentence1 ;;; sentence2 ;;; sentence3
word1 @@@ type2 @@@ sentence4
word2 @@@ type1 @@@ sentence5
上記は、あらゆる UNIX ボックス上のあらゆるシェルのあらゆる awk を使用して動作し、メモリには一度に 1 行のみを保存し、入力と同じ順序で出力を生成します。
答え2
awk での 1 つの方法は次のとおりです。
$ awk -F'@@@' '{ $1 in a ? a[$1][$2]=a[$1][$2]" ;;; "$3 : a[$1][$2]=$3}END{for(word in a){for (type in a[word]){print word,FS,type,FS,a[word][type]} }}' file
word0 @@@ type2 @@@ sentence0
word1 @@@ type1 @@@ sentence1 ;;; sentence2 ;;; sentence3
word1 @@@ type2 @@@ ;;; sentence4
word2 @@@ type1 @@@ sentence5
あるいは、もう少し読みやすく言うと:
awk -F'@@@' '{
if($1 in a){
a[$1][$2]=a[$1][$2]" ;;; "$3
}
else{
a[$1][$2]=$3
}
}
END{
for(word in a){
for (type in a[word]){
print word,FS,type,FS,a[word][type]
}
}
}' file
これには、 Linux システムのデフォルトであるawk
GNU awk ( ) などの多次元配列を理解する実装が必要であることに注意してください。gawk
awk