通过 awk 或 sed 按第一列连接行

tin*_*iny 12 sed awk text-processing

awk在以下情况下如何使用?

我想连接以同一列开头的行。连接后仅保留第一列(在本例中为aaa, www, hhh)。

该文件可以用空格或制表符分隔。

示例输入:

aaa bbb ccc ddd NULL NULL NULL
aaa NULL NULL NULL NULL NULL NULL
aaa bbb ccc NULL NULL NULL NULL
www yyy hhh NULL NULL NULL NULL
hhh 111 333 yyy ooo hyy uuuioooy
hhh 111 333 yyy ooo hyy NULL
Run Code Online (Sandbox Code Playgroud)

期望的输出:

aaa bbb ccc ddd NULL NULL NULL NULL NULL NULL NULL NULL NULL bbb ccc NULL NULL NULL NULL
www yyy hhh NULL NULL NULL NULL
hhh 111 333 yyy ooo hyy uuuioooy 111 333 yyy ooo hyy NULL
Run Code Online (Sandbox Code Playgroud)

这样做的背景是我想建立一个非常简单的基于文件的数据库,其中第一列始终是实体的标识符。基于相同标识符列的所有行都连接在一起。

bin*_*lse 9

要使用 awk 获取每行中的第一列,您可以执行以下操作:

< testfile awk '{print $1}'
aaa
aaa
aaa
www
hhh
hhh
Run Code Online (Sandbox Code Playgroud)

这些是其余行的关键。因此,您可以创建一个哈希表,使用第一列作为键,使用该行的第二列作为值:

< testfile awk '{table[$1]=table[$1] $2;} END {for (key in table) print key " => " table[key];}'
www => yyy
aaa => bbbNULLbbb
hhh => 111111
Run Code Online (Sandbox Code Playgroud)

要获得该行的其余部分,从第 2 列开始,您需要收集所有列:

< testfile awk '{line="";for (i = 2; i <= NF; i++) line = line $i " "; table[$1]=table[$1] line;} END {for (key in table) print key " => " table[key];}'
www => yyy hhh NULL NULL NULL NULL 
aaa => bbb ccc ddd NULL NULL NULL NULL NULL NULL NULL NULL NULL bbb ccc    NULL NULL NULL NULL 
hhh => 111 333 yyy ooo hyy uuuioooy 111 333 yyy ooo hyy NULL 
Run Code Online (Sandbox Code Playgroud)

  • @tiny - 我假设需要保留排序。不是这样吗(这个答案产生与散列机制相对应的排序,而不是您的原始顺序)? (2认同)

ire*_*ses 3

其他人可以用 awk 或 sed 回答,但 Python 版本很简单,可能对您有帮助。

#!/usr/bin/env python

input_file = 'input.dat'
in_fh      = open(input_file, 'r')

input_order = []
seen        = {}
for line in in_fh:    
    # Remove the newline character...
    line = line[:-1]

    # Separate the first column from the rest of the line...
    key_col, sep, rest_of_line = line.partition(" ")
    rest_of_line = sep + rest_of_line  

    # If we've seen this key already, concatenate the line...
    if key_col in seen:
        seen[key_col] += rest_of_line
    # ...otherwise, record the ordering, and store the new info
    else:
        input_order.append(key_col)
        seen[key_col] = rest_of_line

in_fh.close()

# Dump the ordered output to stdout
for unique_col in input_order:
    print unique_col + seen[unique_col]
Run Code Online (Sandbox Code Playgroud)