假设我想获取“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>
.