使用grep -P和lookahead / lookbehind在模式之间获取文本

问题描述

假设file.txt中包含以下内容

---------
foo bar
more foo bar
---------

当我执行grep -P '(?<=-$)(?s:.)*(?=^-)' file.txt时,我希望只匹配中间的两行,但是此表达式不匹配。怎么了? 我也尝试过grep -P '(?s)(?<=-$).*(?=^-)' file.txt,但结果相同。

解决方法

您的模式不起作用,因为

  • P选项仅使用PCRE正则表达式引擎使grep匹配
  • 由于没有其他选项,grep输出完整的匹配行,因此需要添加o选项以输出匹配的文本,并添加z以便将文件插入到单个文字
  • 您的正则表达式默认具有^$锚,它们匹配 string 的开始/结束而不是行。您需要一个m标志和一个s标志(它使.匹配包括换行符的任何字符)。

因此,您可以将正则表达式与m-oz一起使用:

grep -Poz '(?ms)(?<=-$).*(?=^-)' file.txt

或者,

grep -Poz '(?s)-\R\K.*(?=\R-)' file.txt

其中\R插入任何换行序列,而\K则忽略了与整个内存缓冲区相距甚远的文本。

请参见regex demo