将行的以下部分合并到 3 列文件中的当前行

将行的以下部分合并到 3 列文件中的当前行

我有一个文本文件,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

相关内容