每5条记录将一行转换为多行,但使用awk保留第一个字段

时间:2014-09-13 15:33:23

标签: awk

我有一个包含以下模式的文件:

SUB1|p1|p2|p3|p4|p5|p6|p7 
SUB2|p1|p2

现在,所需的输出是:

SUB1|p1|p2|p3|p4|p5  
SUB1|p6|p7  
SUB2|p1|p2

规则是第一个字段(SUB1SUB2等等)是其余字段的标识符(p1p2p3p4p5等等。在p每出现5次之后,它必须转到新行,但是与标识符字段SUB一起。如果p的出现小于5,则必须保持在同一行。

我尝试过:

awk -F'|' '{for(i=1;i<=NF;i++){printf("%s%s",$i,i%6?"|":"\n""|")}}'

它可以在6行后跳转到新行;但不能将SUB保留在新行中。

4 个答案:

答案 0 :(得分:2)

通过GNU sed,

$ sed -r 's/^([^|]*)(\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*)\|(.*)$/\1\2\n\1|\3/g' file
SUB1|p1|p2|p3|p4|p5
SUB1|p6|p7 
SUB2|p1|p2

示例:

$ cat file
SUB1|p1|p2|p3|p4|p5|p6|p7 
SUB2|p1|p2
SUB1|p1|p2|p3|p4|p5|p6
$ sed -r 's/^([^|]*)(\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*)\|(.*)$/\1\2\n\1|\3/g' file
SUB1|p1|p2|p3|p4|p5
SUB1|p6|p7 
SUB2|p1|p2
SUB1|p1|p2|p3|p4|p5
SUB1|p6

答案 1 :(得分:1)

以下是使用perl的替代解决方案:

$ perl -F'\|' -lane 'print join "|", $F[0], splice @F, 1, 5 while @F>1' file
SUB1|p1|p2|p3|p4|p5
SUB1|p6|p7|p8|p9|p10
SUB1|p11
SUB2|p1|p2|p3|p4|p5
SUB2|p6
SUB1|p1|p2|p3|p4|p5
SUB1|p6|p7

说明:

  • -F'\|':将输入字段分隔符设置为|
  • -l:点击换行符并在打印过程中将其放回。
  • -a:根据输入字段分隔符填充数组@F
  • -n:创建一个while(<>) { .. }循环来处理每一行。
  • -e:执行后面的代码块。
  • print join "|", $F[0], splice @F, 1, 5 while @F>1:使用|打印连接在一起的数组中的第一个字段和接下来的五个字段,同时减少数组(使用拼接)。我们继续这样做,直到我们的数组只包含其中的第一个元素。

答案 2 :(得分:1)

awk -F'|' '{for (i=2;i<=NF;i++) printf "%s%s",(i%5==2?(i>2?RS:"")$1:"")FS,$i; print ""}' file

答案 3 :(得分:0)

以下是awk版本:

cat file
SUB1|p1|p2|p3|p4|p5|p6|p7
SUB2|p1|p2
SUB1|p1|p2|p3|p4|p5|p6

awk -F\| '{for (i=2;i<=NF;i++) printf "%s|%s",(i%5==2?RS$1:""),$i} END {print ""}' file

SUB1|p1|p2|p3|p4|p5
SUB1|p6|p7
SUB2|p1|p2
SUB1|p1|p2|p3|p4|p5
SUB1|p6

如果启动时出现空白行是问题,请使用:

awk -F\| '{for (i=2;i<=NF;i++) printf "%s|%s",(i%5==2?(NR==1&&i==2?"":RS)$1:""),$i} END {print ""}' file
SUB1|p1|p2|p3|p4|p5
SUB1|p6|p7
SUB2|p1|p2
SUB1|p1|p2|p3|p4|p5
SUB1|p6