没有点的Perl正则表达式多行匹配
Perl regex multiline match without dot
关于如何在 Perl 中执行多行正则表达式的问题很多。他们中的大多数人都提到了 s
开关,它使点匹配换行符。但是,我想匹配一个确切的短语(所以,不是模式),我不知道换行符在哪里。所以问题是:你能忽略换行符,而不是将它们与.
匹配吗?
MWE:
$pattern = "Match this exact phrase across newlines";
$text1 = "Match\nthis exact\nphrase across newlines";
$text2 = "Match this\nexact phra\nse across\nnewlines";
$text3 = "Keep any newlines\nMatch this exact\nphrase across newlines\noutside\nof the match";
$text1 =~ s/$pattern/replacement text/s;
$text2 =~ s/$pattern/replacement text/s;
$text3 =~ s/$pattern/replacement text/s;
print "$text1\n---\n$text2\n---\n$text3\n";
我可以在模式中放置点而不是空格 ("Match.this.exact.phrase"
),但这对第二个示例不起作用。我可以删除所有换行作为预处理,但我想保留不属于匹配项的换行(如第三个示例)。
期望的输出:
replacement text
---
replacement text
---
Keep any newlines
replacement text
outside
of the match
只需将文字 spaces 替换为匹配 space 或换行符的字符 class:
$pattern = "Match[ \n]this[ \n]exact[ \n]phrase[ \n]across[ \n]newlines";
或者,如果您想更宽松一些,请改用 \s
或 \s+
,因为 \s
也匹配换行符。
它确实很丑,但它确实有效:
M\n?a\n?t\n?c\n?h\st\n?h\n?i\n?s\se\n?x\n?a\n?ct\sp\n?h\n?r\n?a\n?s\n?e\sa\n?c\n?r\n?o\n?s\n?s\sn\n?e\n?w\n?l\n?i\n?n\n?e\n?s
对于一个单词中的每一对字母,在它们之间允许一个换行符\n?
。并将正则表达式中的每个 space 替换为 \s
.
可能无法使用,但它完成了工作 ;)
听起来您想更改 "exact" 模式以匹配任何地方的换行符,并允许换行符而不是空格。所以改变你的模式来这样做:
$pattern = "Match this exact phrase across newlines";
$pattern =~ s/\S\K\B/\n?/g;
$pattern =~ s/ /[ \n]/g;
大多数时候,您将换行符视为空格。如果这就是您想要做的,那么您只需要
$text =~ s/\n/ /g;
$text =~ /\Q$text_to_find/ # or $text =~ /$regex_pattern_to_match/
还有一次你想忽略它。如果这就是您想要做的,那么您只需要
$text =~ s/\n//g;
$text =~ /\Q$text_to_find/ # or $text =~ /$regex_pattern_to_match/
如果您有匹配的正则表达式模式,那么同时执行这两项操作几乎是不可能的。但是你似乎想要匹配文字文本,所以这打开了一些可能性。
( my $pattern = $text_to_find )
=~ s/(.)/ eq " " ? "[ \n]" : "\n?" . quotemeta() /seg;
$pattern =~ s/^\n\?//;
$text =~ /$pattern/
关于如何在 Perl 中执行多行正则表达式的问题很多。他们中的大多数人都提到了 s
开关,它使点匹配换行符。但是,我想匹配一个确切的短语(所以,不是模式),我不知道换行符在哪里。所以问题是:你能忽略换行符,而不是将它们与.
匹配吗?
MWE:
$pattern = "Match this exact phrase across newlines";
$text1 = "Match\nthis exact\nphrase across newlines";
$text2 = "Match this\nexact phra\nse across\nnewlines";
$text3 = "Keep any newlines\nMatch this exact\nphrase across newlines\noutside\nof the match";
$text1 =~ s/$pattern/replacement text/s;
$text2 =~ s/$pattern/replacement text/s;
$text3 =~ s/$pattern/replacement text/s;
print "$text1\n---\n$text2\n---\n$text3\n";
我可以在模式中放置点而不是空格 ("Match.this.exact.phrase"
),但这对第二个示例不起作用。我可以删除所有换行作为预处理,但我想保留不属于匹配项的换行(如第三个示例)。
期望的输出:
replacement text
---
replacement text
---
Keep any newlines
replacement text
outside
of the match
只需将文字 spaces 替换为匹配 space 或换行符的字符 class:
$pattern = "Match[ \n]this[ \n]exact[ \n]phrase[ \n]across[ \n]newlines";
或者,如果您想更宽松一些,请改用 \s
或 \s+
,因为 \s
也匹配换行符。
它确实很丑,但它确实有效:
M\n?a\n?t\n?c\n?h\st\n?h\n?i\n?s\se\n?x\n?a\n?ct\sp\n?h\n?r\n?a\n?s\n?e\sa\n?c\n?r\n?o\n?s\n?s\sn\n?e\n?w\n?l\n?i\n?n\n?e\n?s
对于一个单词中的每一对字母,在它们之间允许一个换行符\n?
。并将正则表达式中的每个 space 替换为 \s
.
可能无法使用,但它完成了工作 ;)
听起来您想更改 "exact" 模式以匹配任何地方的换行符,并允许换行符而不是空格。所以改变你的模式来这样做:
$pattern = "Match this exact phrase across newlines";
$pattern =~ s/\S\K\B/\n?/g;
$pattern =~ s/ /[ \n]/g;
大多数时候,您将换行符视为空格。如果这就是您想要做的,那么您只需要
$text =~ s/\n/ /g;
$text =~ /\Q$text_to_find/ # or $text =~ /$regex_pattern_to_match/
还有一次你想忽略它。如果这就是您想要做的,那么您只需要
$text =~ s/\n//g;
$text =~ /\Q$text_to_find/ # or $text =~ /$regex_pattern_to_match/
如果您有匹配的正则表达式模式,那么同时执行这两项操作几乎是不可能的。但是你似乎想要匹配文字文本,所以这打开了一些可能性。
( my $pattern = $text_to_find )
=~ s/(.)/ eq " " ? "[ \n]" : "\n?" . quotemeta() /seg;
$pattern =~ s/^\n\?//;
$text =~ /$pattern/