合并textblock中的第一行与该块中的每一行

时间:2019-01-17 18:54:24

标签: awk sed

我一直在尝试找出如何使用awk或sed将文本块中的第一行与该块中的其他行合并。每个块由两行或更多行组成,例如:

AA  
1  

BB  
2  
3  
4  

CC  
5  
6  
7  
8  

如何将其合并到下面的输出中:

AA 1  
BB 2  
BB 3  
BB 4  
CC 5  
CC 6  
CC 7  
CC 8  

非常感谢您的帮助。

4 个答案:

答案 0 :(得分:1)

假设符合POSIX的awk和shell *,这将起作用……

awk '/^[[:space:]]*$/ {a=""} {if (a=="") {a=$0} else print a,$0}'

其工作原理的说明(更新):

有两个动作。第一个对空行作出反应(可选的空格除外),因为它前面带有以下模式:/^[[:space:]]*$/。当然,斜线只是分隔图案。插入符号(^)与行的开头匹配,而美元符号($)与行的结尾匹配。这将强制整行匹配(否则,此模式将完全匹配任何行,因为每个可能的输入行都包含零个或多个空白字符)。 [[:space:]]*与预定义字符类的空白字符中的零个或多个(*)字符匹配。此模式的操作会将变量(无谓的a)重置为空字符串。用于检测下一个文本块的开始。

第二个动作没有模式,因此对每个输入行执行一次。它检查是否已设置前缀(再次是变量a),并且:

  • 如果没有,则将前缀设置为当前行($0)的内容。 (请注意,这也无用地在空行上执行。)
  • 如果有,它将打印前缀,后跟当前行的内容。 (awk由于使用逗号而自动插入空格。)

具有讽刺意味的是,我在编写此更新时发现了一个错误:仅包含空格的行将作为前缀。这是因为在这种情况下,检查if (a=="")失败。有多种解决方法。我对awk的了解不足,无法推荐一种特定的方法,但这似乎可以做到:

awk '/^[[:space:]]*$/ {s=1;a=""} {if (s==0 && a=="") a=$0; else print a,$0; s=0}'

*)我最初(懒惰地)写了“ GNU awk and bash”,只是因为那是我用于测试的内容。埃德·莫顿(Ed Morton)指出,我的解决方案不使用任何non-portable features

答案 1 :(得分:1)

$ awk -v RS= '{for (i=2;i<=NF;i++) print $1, $i}' file
AA 1
BB 2
BB 3
BB 4
CC 5
CC 6
CC 7
CC 8

答案 2 :(得分:0)

另一个awk!

$ cat pckh.txt
AA
1

BB
2
3
4

CC
5
6
7
8

$ awk ' NF && !/[A-Z]/ { print prev,$0 } /[A-Z]/ {  prev=$0 }  ' pckh.txt
AA 1
BB 2
BB 3
BB 4
CC 5
CC 6
CC 7
CC 8

$

答案 3 :(得分:0)

GNU sed:

$ sed -rn '/^\s*$/{s/.*//;h;be};/./{x;/./!be;x;G;s/(.*)\n(.*)/\2 \1/p};:e' file
AA 1
BB 2
BB 3
BB 4
CC 5
CC 6
CC 7
CC 8

将空格/制表符也视为空行。
如果没有这样的行,可以更短:

sed -rn '/^$/{h;be};/./{x;/./!be;x;G;s/(.*)\n(.*)/\2 \1/p};:e'