将制表符分隔文件中的两列合并为一列

将制表符分隔文件中的两列合并为一列

我想知道如何将这种格式的数据作为制表符分隔的文件:

A  red     green  
B  yellow  orange  
C  blue    purple  

并使用 grep、paste、cut、cat 等命令将其变成以下内容:

A red
B yellow
C Blue
A green
B orange
C purple

答案1

与 cut 类似,您也可以使用 awk 来完成:

$ awk '{print $1,$2}' aa.txt && awk '{print $1,$3}' aa.txt
A red
B yellow
C blue
A green
B orange
C purple
# OR to send the output in a new file:
$ (awk '{print $1,$2}' aa.txt && awk '{print $1,$3}' aa.txt) >aaa.txt

不同之处在于 awk 比 cut 更好地处理空白。如果每一行中的字段由多个空格分隔,则此功能很有用。

例如,如果文件行A red= 1 个空格分隔,那么按照建议的 cut 解决方案也可以成功,但如果行 = A red3 个空格,那么 cut 将失败,而 awk 将成功获取字段 1 和 2 或字段 1和 3.

更新:
正如评论中所建议的(感谢 don_crissti),这也可以在纯 awk 中完成:

awk 'BEGIN{FS=OFS=" "}{z[NR]=$1FS$3; print $1,$2}END{for (i=1; i<=NR; i++){print z[i]}}' a.txt

解释:

FS           : Input Field Separator
OFS          : Output Field Separator
FS=OFS=" "   : input & output field separator is set to "space"
z[NR]        : Creating an array with name 'z' and index the record number: 
             z[1] for first line, z[2] for second line , z[3] for third line
z[NR]=$1FS$3 : to each array element assign field1-FieldSeparator FS=space)-field2
So for first line the fields1=A and Fields 3=green will be stored in z[1] => equals to z[1]="A green"

print $1,$2  : Justs prints on screen 1stfield (A) and 2ndfield (red) of the current line, printed separated by OFS

When the file is finished (END) then with a for loop we print out the whole z array entries => print z[i]
For i=1 => print z[1] => prints "A green"
For i=2 => print z[2] => prints "B orange"
For i=3 => print z[3] => prints "C purple"

PS: If fields are not separated by space but by tab , then Begin section of this awk one-liner must be changed to `awk 'BEGIN {FS=OFS="\t"}....`

答案2

仅使用cut,如果您不介意写入文件(如果需要,请先复制原始文件),您可以使用:

$ cut -f 1,3 file >> file && cut -f 1,2 file
A   red
B   yellow
C   blue
A   green  
B   orange  
C   purple 

解释

  • cut -f 1,3 file打印第一列和第三列file(大部分由制表符分隔)
  • >> file将输出附加到file而不是显示在终端中
  • &&如果有效,请执行下一个命令
  • cut -f 1,2 filefile仅在终端中打印第一列和第二列。

请注意,它file本身最终看起来像这样:

A   red     green  
B   yellow  orange  
C   blue    purple  
A   green  
B   orange  
C   purple  

因此,要在文件中获得所需的最终输出,您需要重定向到新文件。

cut -f 1,3 file >> file && cut -f 1,2 file > file2

答案3

与 Zanna 的解决方案类似,但没有中间文件/结果:

$ ( cut -f1,2 data && cut -f1,3 data ) >data.new

子 shell 的输出被放入最终文件中data.new。子 shell 首先提取前两列,然后提取第一列和第三列。

答案4

awk '{print 1 $1,$2; print 2 $1,$3}' ex |sort |cut -c 2-

更新:为了保证订单被保留:

awk '{print 1,$1,$2; print 2,$1,$3}' ex |sort -sk1,1 |cut -c 3-
  • sort -sk1,1具有稳定的第一字段排序

(\谢谢{Kusalananda})

相关内容