多行上的 sed 正则表达式无法捕获所有

Posted

技术标签:

【中文标题】多行上的 sed 正则表达式无法捕获所有【英文标题】:sed regex on multiple line can't capture all 【发布时间】:2021-10-07 15:35:30 【问题描述】:

我有这个文本文件(示例)

<This is a line of text with a year=2020 month=12 in it
This line of text does not have a year or month in it
This year=2021 is the current year the current month=1
This is the year=2021 the month=2/>


<This is a line of text with a year=33020 month=12 in it
This line of text does not have a year or month in it
This year=33020 is the current year the current month=1
This is the year=33020 the month=2/>

使用 linux sed (sed (GNU sed) 4.2.2) 正则表达式:

 sed -En 'N;s/\<(This.*2020.*[\s\S\n]*?)\>/\1/gp' test2.txt

它只捕获这个字符串:

<This is a line of text with a year=2020 month=12 in it
This line of text does not have a year or month in it

我尝试将 之间的第一段捕获为组

我在这里做错了什么?

【问题讨论】:

难道\&lt;\&gt; 有时也用作单词分隔符? 你这是什么意思? 我的意思是 GNU sed 正则表达式使用 \&lt;\&gt; 作为单词的开始和结束分隔符。 【参考方案1】:

如果您想打印以&lt;This 开头、包含2020 且仅包含它们的段落(由&lt;...&gt; 分隔),您可以尝试:

sed -En '/^</!d;:a;/>$/!N;ba;;/<This.*2020/p;' test2.txt

只要模式空间不以&lt;开头,就会被删除并开始一个新的循环(/^&lt;/!d)。

然后,只要模式空间不以&gt; 结尾,就会追加新行,但不会开始新的循环,而是跳转到a 标签(/&gt;$/!N;ba;)。

当整个段落存储在模式空间中时,我们退出此循环并应用最后一个命令 (^&lt;This.*2020/p):如果模式空间与您的模式匹配,则将其打印。终于,一个新的循环开始了。

当然,正则表达式必须适应您的需要。如果段落分隔符可以在空格之前(之后),例如,使用:

sed -En '/^[[:space:]]*</!d;:a;/>[[:space:]]*$/!N;ba;;/<This.*2020/p;' test2.txt

【讨论】:

我用这个命令修复了它: sed -i -En '/./H;$!d ; X ; s///p' test2.txt 但现在我有新问题要检查? unix.stackexchange.com/questions/662974/…【参考方案2】:

使用 GNU Awk,您可以将 RS 指定为正则表达式。

bash gawk -v RS='[<>]' /This.*2020/ <<\:
> <This is a line of text with a year=2020 month=12 in it This line of
> text does not have a year or month in it This year=2021 is the current
> year the current month=1 This is the year=2021 the month=2/>
> 
> <This is a line of text with a year=33020 month=12 in it This line of
> text does not have a year or month in it This year=33020 is the
> current year the current month=1 This is the year=33020 the month=2/>
> :
This is a line of text with a year=2020 month=12 in it
This line of text does not have a year or month in it
This year=2021 is the current year the current month=1
This is the year=2021 the month=2/

如您所见,这也会修剪分隔符;但添加回来并不难(提示: print "&lt;" $0 "&gt;" )。

【讨论】:

以上是关于多行上的 sed 正则表达式无法捕获所有的主要内容,如果未能解决你的问题,请参考以下文章

捕获包含模式正则表达式的每个单词

使用 sed 和正则表达式处理多行日志文件

具有捕获组的有效正则表达式,但 sed 脚本不起作用

Python: 正则表达式匹配多行,实现多行匹配模式

aix 上的 sed 正则表达式问题

AIX 上的 sed 正则表达式问题(第 2 部分)