将块中的行转换为制表符分隔符

时间:2016-06-29 01:23:46

标签: linux unix awk sed

我在2个块中有以下行(实际上有~10K)。 在这个例子中,每个块包含3行。但实际上它是6行。

xox
91-233
chicago

koko
121-111
alabama

我想把它变成

xox  91-233  chicago
koko 121-111 alabama

我该怎么做?

我尝试了tr "\n" "\t",但没有做我想做的事。

5 个答案:

答案 0 :(得分:4)

$ awk -F'\n' '{$1=$1} 1' RS='\n\n' OFS='\t' file
xox     91-233  chicago
koko    121-111 alabama 

如何运作

Awk将输入划分为记录,并将每个记录划分为字段。

  • -F'\n'

    这告诉awk使用换行符作为字段分隔符。

  • $1=$1

    这告诉awk将第一个字段分配给第一个字段。虽然这似乎什么都不做,但它会导致awk将记录视为已更改。因此,使用我们为ORS指定的值(输出记录分隔符)打印输出。

  • 1

    这是用于打印线条的awk简洁速记。

  • RS='\n\n'

    这告诉awk将两个连续的换行视为记录分隔符。

  • OFS='\t'

    这告诉awk使用选项卡作为输出的字段分隔符。

答案 1 :(得分:3)

另一种选择,

$ sed '/^$/d' file | pr -3ats$'\t'

xox     91-233  chicago
koko    121-111 alabama

删除sed的空行,并使用制表符分隔符打印到3列。在您的真实文件中,这应该是块中的行数。

请注意,这仅适用于所有块的大小相同的情况。

答案 2 :(得分:3)

这个答案提供以下内容:
*它适用于任何大小的非空行块,由任意数量的空行分隔; John1024's helpful answer(类似且首先出现)适用于由一个空行分隔的行块。
*它解释了详细使用的awk命令。

更具惯用性(POSIX兼容)awk解决方案:

awk -v RS= -F '\n' -v OFS='\t' '$1=$1""' file
  • -v RS=告诉awk模式运作:考虑每次非空单 em>记录; RS是输入记录分隔符。

    • 注意:这意味着此解决方案将一个或更多空行视为分隔段落(行块); empty 表示:根本没有行内部字符,甚至没有空格。
  • -F '\n'告诉awk将输入段落的每一行视为自己的字段(将多行输入记录按行划分为字段); -F设置FS,输入字段分隔符。

  • -v OFS='\t'告诉awk输出上用\t(标签字符)分隔字段; OFS是输出字段分隔符。

  • $1=$1""看似无操作,但是,由于分配给字段变量$1(记录的第一个字段),使用awk作为字段分隔符,OFS 重建输入记录,从而有效地将\n分隔符替换为\t

    • 尾随""用于防止在数字上下文中评估为0的段落中第一行的边缘情况;附加""强制处理为字符串,任何非空字符串 - 即使它包含"0" - 在布尔上下文中被视为 true - 请参阅下方。
  • 鉴于$1定义为非空,并且假定awk中的作业通过其值,则作业$1=$1""的结果也是非空字符串;由于赋值用作模式(条件),非空字符串被视为 true ,并且没有关联的操作块( { ... }),隐含操作打印 - 重建 - 输入记录,现在包含用标签分隔的输入行,由默认输出记录分隔符(ORS),\n终止。

答案 3 :(得分:3)

xargs -L3 < filename.log |tr ' ' '\t'
xox 91-233 chicago
koko 121-111 alabama

答案 4 :(得分:2)

另一个版本的awk来做这个

 awk '{if(NF>0){a=a$1"\t";i++};if(i%3==0&&NF>0){print a;a=""}}' input_file