你链接到自己的documentation 对我来说似乎很清楚。如果您能解释一下您在理解它时遇到了什么问题,以及您如何认为 /s 和 /m 是对立的,这将有所帮助。
非常简单地说,/s 改变了点元字符 . 的行为,使其完全匹配任何字符。通常它匹配除换行符"\n" 之外的任何内容,因此即使字符串包含换行符,它也会将字符串视为s单行。
/m 修改插入符号^ 和美元$ 元字符,以便它们匹配字符串内 的换行符,将其视为m多行细绳。通常它们只会在字符串的开头和结尾匹配。
您不应该对 /g 修饰符“贪婪”感到困惑。它用于 global 匹配,它将在字符串中找到 所有 出现的模式。 greedy 一词通常用于表示模式中 量词的行为。例如,.* 被认为是贪婪的,因为它会匹配尽可能多的字符,而 .*? 会匹配尽可能少的字符。
更新
在您修改后的问题中,您使用的是/".*"/mg,其中/m 无关紧要,因为如上所述,该修饰符仅改变$ 和^ 元字符的行为,并且没有你的模式。
将其更改为 /".*"/sg 会稍微改进一点,因为 . 现在可以匹配每行末尾的换行符,因此该模式可以匹配多行字符串。 (请注意,这里的 object 字符串被认为是 "single line" - 即匹配行为就好像其中没有换行符一样,直到 @涉及到 987654339@。)这里是 greedy 的传统含义,因为该模式现在匹配从第一行的第一个双引号到最后一个双引号的所有内容。线。我想这不是你想要的。
有几种方法可以解决此问题。我建议更改您的模式,以便您想要的字符串是双引号,后跟任何字符序列除了双引号,然后是另一个双引号。这写成/"[^"]*"/g(请注意,/s 修饰符不再需要,因为现在模式中没有点)并且几乎可以满足您的要求,只是转义的双引号被视为模式的结束。
看看这个程序及其输出,注意我在每场比赛的开头都放了一个雪佛龙>>,以便区分它们
use strict;
use warnings;
my $file = do {
local $/;
<DATA>;
};
my @strings = $file =~ /"[^"]*"/g;
print ">> $_\n\n", for @strings;
__DATA__
"This is string"
"1!=2"
"This is \"string\""
"string1"."string2"
"String"
"S
t
r
i
n
g"
输出
>> "This is string"
>> "1!=2"
>> "This is \"
>> ""
>> "string1"
>> "string2"
>> "String"
>> "S
t
r
i
n
g"
如您所见,现在一切正常,除了在"This is \"string\"" 中找到了两个匹配项"This is \" 和""。解决这个问题可能比你想的要复杂,但这是完全可能的。如果您也需要修复,请说出来。
更新
我不妨把这件事结束。要忽略转义的双引号并将它们视为字符串的一部分,我们需要接受 either \" 或 除双引号之外的任何字符。这是使用正则表达式交替运算符| 完成的,并且必须分组在非捕获括号(?: ... ) 内。最终结果是/"(?:\\"|[^"])*"/g(反斜杠本身必须被转义,所以它加倍),当放入上述程序时,会产生这个输出,我认为这就是你想要的。
>> "This is string"
>> "1!=2"
>> "This is \"string\""
>> "string1"
>> "string2"
>> "String"
>> "S
t
r
i
n
g"