我有一个文本文件,word @@@ type @@@ sentence
每一行都有格式,按“单词”升序排序。然而,有些行不是唯一的,它们以与前一行相同的单词开头,即参见下面的 word1:
...
word0 @@@ type2 @@@ sentence0
word1 @@@ type1 @@@ sentence1
word1 @@@ type1 @@@ sentence2
word1 @@@ type1 @@@ sentence3
word1 @@@ type2 @@@ sentence4
word2 @@@ type1 @@@ sentence5
...
我想通过附加句子将具有相同单词和类型组合的行合并为一行,因此文件结果为:
...
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 机器上的任何 shell 中使用任何 awk 来工作,一次只在内存中存储 1 行,并且将按照与输入相同的顺序生成输出。
答案2
这是 awk 中的一种方法:
$ 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
请注意,这需要一个awk
能够理解多维数组的实现,例如 GNU awk ( ),这是Linux 系统上的gawk
默认实现。awk