跨一行或多行提取第一个匹配项和第一个不同匹配项之间的内容

跨一行或多行提取第一个匹配项和第一个不同匹配项之间的内容

假设我想获取“start_”的第一个匹配项和“_end”的第一个匹配项之间的文本,无论它是跨同一行或多行。不要包括匹配项。

示例文本1:

This is a start_text with start_and some_end text with_end

输出文本1:

text with start_and some

示例文本2:

This is a
start_text with
start_and some_end
text with_end

输出文本2:

text with
start_and some

我看过很多答案,但它们都是以行为中心,而不是以文件为中心。任何类型的工具或命令都可以,只要它是基于控制台的。

答案1

perl

$ perl -l -0777ne 'print $1 while /start_(.*?)_end/gs' your-example-2
text with
start_and some
  • perl -n是为每个运行所sed -n提供的表达式的模式e线的输入,如sed.
  • -l是为了在ingl时自动附加一个新的ineprint
  • -<octal-number>将记录分隔符设置为具有给定值的字节而不是换行符。0777(511) 或任何高于 0377 (255) 的值都是无法存在的字节值,因此只会有一条记录:整个文件。
  • *?like*匹配 0 个或多个前面的原子(此处.匹配任何单个字符),但 while*会匹配尽可能多的原子,*?匹配尽可能少的原子,因此.*?将运行直到第一次出现_end,而不是最后一次。
  • s模式匹配运算符的标志也/regexp/需要.匹配换行符,但默认情况下并不匹配。

你应该也可以使用pcregrep,但是我发现(Debian 的版本 8.39 2016-06-14)它给出了:

$ pcregrep -Mo1 '(?s)start_(.*?)_end' your-example-2
text with
start_and some
and some

我无法解释。pcre2grep(版本 10.42 2022-12-11)不过可以:

$ pcre2grep -Mo1 '(?s)start_(.*?)_end' your-example-2
text with
start_and some

1 从技术上讲,它会导致在存储之前从输入中剥离记录分隔符$_ 输出记录分隔符 ( $\) 设置为与输入记录分隔符 ( $/) 相同,此时输入记录分隔符仍然是换行符,因此重要的是它-l位于-0....请注意,-l<octal>将输出记录分隔符设置为给定的字节值,因此它与-l -<octal>.

相关内容