我有一个来自此示例的 awk
脚本:
awk '/START/{if (x) print x; x="";}{x=(!x)?$0:x","$0;}END{print x;}' file
这是一个带有行的示例文件:
$ cat file
START
1
2
3
4
5
end
6
7
START
1
2
3
end
5
6
7
所以我需要停止在目标字符串包含 end
Word时停止连接,因此所需的输出为:
START,1,2,3,4,5,end
START,1,2,3,end
短 Awk
解决方案(尽管它将两次检查/end/
模式):
awk '/START/,/end/{ printf "%s%s",$0,(/^end/? ORS:",") }' file
输出:
START,1,2,3,4,5,end
START,1,2,3,end
-
/START/,/end/
- range 模式
a 范围模式由两种图案制成 表格
‘begpat, endpat’
。它用于匹配连续的范围 输入记录。第一个模式begpat
控制范围的位置 开始,当endpat
控制模式结束的位置。
-
/^end/? ORS:","
-设置范围内当前项目的定界符
这是另一个awk
$ awk '/START/{ORS=","} /end/ && ORS=RS; ORS!=RS' file
START,1,2,3,4,5,end
START,1,2,3,end
请注意,/end/ && ORS=RS;
缩短了/end/{ORS=RS; print}
您可以使用此awk
:
awk '/START/{p=1; x=""} p{x = x (x=="" ? "" : ",") $0} /end/{if (x) print x; p=0}' file
START,1,2,3,4,5,end
START,1,2,3,end
另一种方式,类似于如何在两个模式之间选择行的答案?
$ awk '/START/{ORS=","; f=1} /end/{ORS=RS; print; f=0} f' ip.txt
START,1,2,3,4,5,end
START,1,2,3,end
- 这不需要缓冲区,但不检查
START
是否具有相应的end
-
/START/{ORS=","; f=1}
将ORS设置为,
,并设置标志(控制要打印的行) -
/end/{ORS=RS; print; f=0}
在结束条件下将ORS设置为newline。打印行并清除标志 -
f
打印输入记录只要设置此标志
,因为我们似乎已经沿着兔子洞走了下来的方法,所以对于Multi-Char RS,RT,RT和Gensub(),GNU Awk是一种相当合理的方法:
$ awk -v RS='end' -v OFS=',' 'RT{$0=gensub(/.*(START)/,"\1",1); $NF=$NF OFS RT; print}' file
START,1,2,3,4,5,end
START,1,2,3,end