PHP Regex:如何在不使用 [\r\n] 的情况下匹配 \r 和 \n?

Posted

技术标签:

【中文标题】PHP Regex:如何在不使用 [\\r\\n] 的情况下匹配 \\r 和 \\n?【英文标题】:PHP Regex: How to match \r and \n without using [\r\n]?PHP Regex:如何在不使用 [\r\n] 的情况下匹配 \r 和 \n? 【发布时间】:2013-09-30 01:52:21 【问题描述】:

我已经测试了\v(垂直空白)以匹配\r\n 及其组合,但我发现\v 不匹配\r\n。下面是我正在使用的代码..

$string = "
Test
";

if (preg_match("#\v+#", $string )) 
  echo "Matched";
 else 
  echo "Not Matched";

为了更清楚,我的问题是,有没有其他选择可以匹配\r\n

【问题讨论】:

我猜你可以使用\s+。有什么理由不想使用\r\n @Jerry: \s 匹配任何空白 是的,我知道,但您要求替代匹配 \r\n,而 \s 确实匹配。 @Jerry: 好的,但它不仅仅是 macthes \r\n,我猜想 \v 可以解决问题,但它没有 @Jerry 请参阅我下面的答案,而不是 \s 您可以使用 PCRE 中使用的 \R 【参考方案1】:

PCRE 和换行符

PCRE 有多余的换行符相关的转义序列和替代方案。

嗯,你可以在这里使用的一个漂亮的转义序列是\R。默认情况下,\R 将匹配 Unicode 换行符序列,但可以使用不同的替代方案进行配置。

匹配 ASCII 范围内的任何 Unicode 换行符序列。

preg_match('~\R~', $string);

这相当于下面的组:

(?>\r\n|\n|\r|\f|\x0b|\x85)

匹配任何 Unicode 换行序列;包括ASCII 范围之外的换行符以及行分隔符 (U+2028) 和段落分隔符 (U+2029),您想要打开 u (unicode) 标志。

preg_match('~\R~u', $string);

u (unicode) 修饰符打开 PCRE 的附加功能,并且模式字符串被视为 (UTF-8)。

相当于下面的组:

(?>\r\n|\n|\r|\f|\x0b|\x85|\x2028|\x2029)

可以将\R 限制为仅匹配CRLFCRLF

preg_match('~(*BSR_ANYCRLF)\R~', $string);

相当于下面的组:

(?>\r\n|\n|\r)

附加

支持在字符串中指示换行符的五种不同约定:

(*CR)        carriage return
(*LF)        linefeed
(*CRLF)      carriage return, followed by linefeed
(*ANYCRLF)   any of the three above
(*ANY)       all Unicode newline sequences

注意\R 在字符类中没有特殊含义。与其他无法识别的转义序列一样,默认情况下将其视为文字字符“R”。

【讨论】:

哇!我从来没有使用过它,这就是我要找的:) 看这个例子:phpfiddle.org/main/code/phd-ebj 此答案已添加到 Stack Overflow Regular Expression FAQ 的“转义序列”下。 +1 表示\R。仅出于学术目的,如果您不在u 模式下,您可以发明这种匹配\r\n 的其他方式而不使用它们:(?![ \t\cK\f])\s 为什么?因为\s 匹配[ \t\cK\f\r\n],所以这是类减法的一种形式。 :) 小心。我在使用带有俄语单词的捕获组“~\R~”时遇到了问题。当此正则表达式应用于单词“необходимости”时,它变为“необ�одимости”。 @PedroSousa 为什么省略 u 模式修饰符?当你想读取输入字符串中的多字节字符时,你需要告诉正则表达式引擎。【参考方案2】:

这并不能回答替代品的问题,因为\v 工作得很好

\v 匹配任何被视为垂直空格的字符; 这包括平台的回车和换行字符(换行符)以及其他几个字符,所有这些都列在下表中。

您只需将"#\v+#"更改为任一

"#\\v+#" 转义反斜杠

'#\v+#' 使用单引号

在这两种情况下,您都会得到\r\n 的任意组合的匹配项。

更新:

只是为了让\v 的范围与\R 相比更清楚,来自perlrebackslash

\R\R 匹配通用换行符;也就是说,任何被 Unicode 视为换行序列的东西。 这包括\v匹配的所有字符(垂直空格),...

【讨论】:

【参考方案3】:

如果有一些奇怪的要求阻止您在模式中使用文字 [\r\n],您始终可以使用十六进制转义序列:

preg_match('#[\xD\xA]+#', $string)

这是模式等价于[\r\n]+

【讨论】:

【参考方案4】:

要匹配给定字符串的每一行,只需使用^$ 锚并建议您的正则表达式引擎在多行模式下运行。然后^$ 将匹配每一行的开始和结束,而不是整个字符串的开始和结束。

http://php.net/manual/en/reference.pcre.pattern.modifiers.php

在 PHP 中,这将是模式之后的 m 修饰符。 /^(.*?)$/m 将简单匹配每一行,由给定字符串内的任何垂直空格分隔。

顺便说一句:对于分行,您还可以使用 split()PHP_EOL 常量:

$lines = explode(PHP_EOL, $string);

【讨论】:

【参考方案5】:

问题是你需要 multiline 选项,如果使用 dot 则需要 dotall 选项。它位于分隔符的末尾。

http://www.php.net/manual/en/regexp.reference.internal-options.php

$string = "
Test
";
if(preg_match("#\v+#m", $string ))
echo "Matched";
else
echo "Not Matched";

【讨论】:

这不是让 \v 匹配 \r\n 多行模式无关紧要。许多正则表达式用户会得出结论,只要目标字符串包含行分隔符,您就必须指定多行模式。它所做的只是调整锚点的行为(^$),因此它们将在行边界处匹配(即行分隔符之前和之后)。 OP 的正则表达式不包含任何锚。【参考方案6】:

要匹配 PHP 中的换行符,请使用 php 常量 PHP_EOL。这是跨平台的。

if (preg_match('/\v+' . PHP_EOL ."/", $text, $matches ))
   print_R($matches );

【讨论】:

当心贪婪的比赛!你可能会得到太多。【参考方案7】:

此正则表达式还匹配换行符\n 和回车符\r

(?![ \t\f])\s

DEMO

要匹配一个或多个换行符或回车符,您可以使用下面的正则表达式。

(?:(?![ \t\f])\s)+

DEMO

【讨论】:

以上是关于PHP Regex:如何在不使用 [\r\n] 的情况下匹配 \r 和 \n?的主要内容,如果未能解决你的问题,请参考以下文章

PHP/regex:如何获取 HTML 标签的字符串值?

如何在任何编辑器中通过 Regex 删除所有单行 PHP 注释行

如何使用带有 PHP 的 Azure 通知中心发送通知?

使用 PHP Regex 或 DOM,如何在标签之间使用 eol 或换行符获取网页的 <TITLE>?</TITLE>?

匹配换行符 - \n 或 \r\n?

Twig / PHP - 使用Replace或Regex格式化字符串