【发布时间】:2021-08-27 13:54:04
【问题描述】:
下面的例子:
$text = <<<END
some text
q 1
some next line
q 2 test
exptra line
END;
$text = trim($text);
if (preg_match_all("/\nQ\s+\d+.[^\n]*\n/isU", $text, $match)) {
print_r($match);
echo "OK";
} else {
echo "FAIL";
}
输出:
Array
(
[0] => Array
(
[0] =>
q 1
some next line
[1] =>
q 2 test
)
)
OK
请注意,$text 示例中的新行仅包含一个 \n。
出于某种原因.[^\n]* 包含换行符,即使它被声明为排除。仅当换行符是与这部分表达式匹配的唯一符号(\n 紧跟在 1 之后)和星号(*)时才会发生,这应该意味着包括无/可选在内的任意数量的字符都不会在此处播放正确。
由于我需要匹配这两种情况,在这种情况下可以做什么?
预期的输出,匹配以q N 开头但不包含以下行的两行:
Array
(
[0] => Array
(
[0] =>
q 1
[1] =>
q 2 test
)
)
上面的例子是简化的。匹配的字符串可以包含换行符,但不能在指定位置。实际上我用其他符号测试了.,它的工作原理是一样的。如果 dot 剩下的唯一字符是表示为 exclude 的字符 - 它仍然包含它:
$text = <<<END
some text
q 1e
some next line
q 2 test
exptra line
END;
$text = trim($text);
if (preg_match_all("/Q\s+\d+.[^e]*/iU", $text, $match)) {
print_r($match);
echo "OK";
} else {
echo "FAIL";
}
输出:
Array
(
[0] => Array
(
[0] => q 1e
[1] => q 2
)
)
【问题讨论】:
-
.匹配\n因为你有s标志。[^\n]*matches 零 或更多非LF,因此它不限制.这里。您希望在这里得到什么? -
试试
preg_match_all('~^Q\h+\d.*~im', $text, $matches)。见the regex demo。 -
添加了预期的输出。来自
s修饰符文档A negative class such as [^a] always matches a newline character,因此对于这种情况,s修饰符是否到位并不重要。\n声明为“排除”字符,不应像第二种情况一样包含在内。 -
s标志修改了.的行为,而不是[^a],您对这里的文档感到困惑。 -
我的意思是
.[^a]根据文档无论如何都包含换行符,无论s是否存在。