在Linux中合​​并文本文件的两列

时间:2015-04-09 19:51:58

标签: linux bash

我有一个包含多列文本和值的文本文件。这个结构:

CAR       38
     DOG  42
CAT       89
CAR       23
     APE  18

如果第1列有String,则第2列不具有(或者它实际上是一个emptry String)。反过来说:如果第1列为空,则第2列有一个字符串。换句话说,“对象”(CAR,CAT,DOG等)出现在第1列或第2列中,但绝不会同时出现。

我正在寻找一种有效的方法来整合第1列和第2列,以便文件看起来像这样:

CAR  38
DOG  42
CAT  89
CAR  23
APE  18

我可以使用while和if在Bash脚本中执行此操作,但我确信有一种更简单的方法。有人可以帮忙吗?

干杯! ž

2 个答案:

答案 0 :(得分:17)

试试这个:

column -t file

输出:

CAR  38
DOG  42
CAT  89
CAR  23
APE  18

答案 1 :(得分:8)

注意:如果:

  • 您正在寻找带有自动调整大小的左对齐固定宽度列的输出(最长的字段值确定宽度,较短的值用空格右边填充)
  • 并且对两个空格作为列分隔符
  • 感到满意
  • 并且正在使用足够小的文件来读取整个内存

使用Cyrus's simpler, column-based answer

请参阅下文,了解基于column的方法在性能和资源消耗方面与基于awk的方法的比较。


awk 是您的朋友:

awk -v OFS='  ' '{ print $1, $2 }' file
  • awk默认情况下会按空格将行拆分为字段,因此,对于您的输入,CAR 38DOG 42等行的解析方式相同(CAR和{{ 1}}成为字段1,DOG$138成为字段2,42)。
  • $2将输出字段分隔符设置为两个空格(默认为单个空格);请注意,输出值不会有 padding 来创建对齐输出。

要使用不同宽度的字段创建对齐输出,请使用Awk的-v OFS=' '函数,它可以让您更好地控制输出;例如,以下输出一个10字符宽的左对齐第一列,以及一个2字符宽的右对齐第二列:

printf
  • 请注意,列宽必须事先知道。
  • 相比之下,awk '{ printf "%-10s %2s\n", $1, $2 }' file 通过首先解析所有数据,方便地自动确定列宽,但这会影响性能和资源消耗;见下文。

column -t与Awk方法之间的效果/资源消耗比较

  • column -t需要在第一遍中预先分析所有输入数据,以便能够确定最大输入列宽度;从我所知道的,它首先将输入作为一个整体读入内存,这对于大输入文件可能会有问题。
  • 相比之下,Awk解决方案逐个读取行 - 但依赖于提前知道列宽。

因此,

  • column -t消耗与输入大小成比例的内存,而column -t将使用常量内存
  • awk 通常较慢,具体取决于所使用的Awk实现; column -t要快得多,mawk要快一点,BSD gawk要慢一些(!);基于1000万行输入文件的结果;命令在OSX 10.10.2和Ubuntu 14.04上运行。