awk中行尾与记录尾区分:匹配行尾数字输出指定段落
问题描述
需要匹配行尾为数字200(用$锚定)的段落,忽略第三段。数据如下:
this is first paragraph number 200 with some text this is second paragraph with some text number 200 this is third paragraph with some text number 2001
使用awk -v RS="" -v ORS="\n\n" "/number 200\n/" file仅匹配第一段;使用awk -v RS="" -v ORS="\n\n" "/number 200$/" file仅匹配第二段——问题在于awk将$识别为**记录尾(段落尾)**而非行尾。现在需要在无原生段落处理支持的grep中,优雅解决这个问题,预期输出:
this is first paragraph number 200 with some text this is second paragraph with some text number 200
解决方案
可以结合grep的多选项与PCRE正则实现需求,以下是两种可行方案:
方案1:使用标准grep(支持-z/-P选项)
grep -zPo '(?s)(^|\n\n)(.*?number 200\n.*?)(?=\n\n|\z)' file | tr '\0' '\n'
命令细节解释
-z:将整个文件视为单个连续流(用NUL字符作为记录分隔符),突破grep默认按行处理的限制。-P:启用Perl兼容正则表达式,支持单行模式、正向预查等高级特性。-o:仅输出匹配到的目标内容,而非整文件/整行。- 正则规则:
(?s):开启单行模式,让.可以匹配换行符,实现跨多行的段落匹配。(^|\n\n):匹配段落起始位置——要么是文件开头,要么是两个换行符(段落分隔标记)。(.*?number 200\n.*?):非贪婪匹配段落内容,确保包含行尾为200的行(number 200\n避免误匹配2001这类后缀)。(?=\n\n|\z):正向预查段落结束位置——要么是下一个段落的分隔符(两个换行符),要么是文件结尾。
tr '\0' '\n':将grep-z模式输出的NUL字符转换回换行符,恢复正常格式。
方案2:使用pcregrep(专门PCRE工具)
如果你的环境中有pcregrep,命令更简洁:
pcregrep -M '(^|\n\n).*?number 200\n.*?(?=\n\n|\z)' file
-M选项直接允许正则表达式跨多行匹配内容,无需额外处理流格式。
内容的提问来源于stack exchange,提问作者user3602441
相关产品推荐
相关产品推荐

