如何使用正则表达式删除字符串末尾的\n
的最大数量?
\n
删除符合字符串^
开头的搜索位置时的预期,但是当搜索位置在字符串末尾时,我无法获得正确的结果。
$subject = "\n\n\nsubject\n\n\n";
# maximum removal
$count = 2;
# expect maximum 2 LF removed, 2 removed
var_dump(preg_replace("#^\\n{0,$count}#",null,$subject));
# expect maximum 2 LF removed, 3 removed
var_dump(preg_replace("#\\n{0,$count}\$#",null,$subject));
然而,当使用\ r时,两个脚本都按预期结果
答案 0 :(得分:1)
要在字符串末尾删除一些特定数量的换行符的正则表达式,您需要使用匹配在字符串末尾的\z
锚点:
$subject = "\n\n\nsubject\n\n\n";
$count = 2;
echo preg_replace("#\n{1,$count}\\z#",null,$subject);
请参阅IDEONE demo
$
锚点可能会在字符串的最后一个换行符处匹配,因此您无法使用它。此外,没有必要匹配0个换行符来删除它们,因此,1
应该是限制量词的下限。
但是,您可以使用$
修饰符( PCRE_DOLLAR_ENDONLY修饰符)在字符串的最后匹配/D
:
preg_replace("#\n{1,$count}$#D",null,$subject)
^^^
以下是PHP PCRE documentation的一些相关摘录:
美元字符(
$
)是一个断言,只有当前匹配点位于主题字符串的末尾 或之前, TRUE 换行符是字符串中的最后一个字符(默认情况下) 。 ... 通过在编译或匹配时设置PCRE_DOLLAR_ENDONLY
选项,可以更改美元的含义,使其仅在字符串的最后匹配。 / p>
回答评论:
问题OP 仅在字符串末尾删除特定数量的换行符号(NOT \r\n
,混合\r
或\r\n
)。注意,不是在最后一个非换行符之后,而是在字符串的末尾。现在让我们测试当前的解决方案(参见the demo code)。请注意,下面的代码不会删除换行符,而是替换为文字\n
序列,以查看实际替换的内容。
$subject = "subject\n\n\n";
$count = 2;
echo preg_replace("#\\n{0,$count}\$#","\\n",$subject); // OP - "subject\n\n\n"
echo '"'.preg_replace("#\n{1,$count}\\z#","\\n",$subject).'"'; // mine removes 2 at the end:
//"subject
//\n"
echo '"'.preg_replace("#(?:\r?\n){1,$count}$#","\\n",$subject).'"';//sln's - "subject\n\n"
所以,这里我们需要在字符串末尾删除2个(或者如果没有2个)换行符号,该符号有3个换行符号。这意味着,预期结果为"subject\n"
。
"subject\n
" - OP需要什么。让我们比较OP和我的正则表达式如何与preg_replace
对"\n\n\nsubject\n\n\n"
字符串一起使用:
\n{0,2}$
- 找到前2个\n
,但$
无法断言字符串的结尾,并且进一步的回溯未找到字符串位置的结尾 - &gt ;检查下一个位置。然后发生同样的事情(再次2 \n
s不在字符串结束之前)。然后有一个\n
和s
- >另一个失败,因为s
不是字符串的结尾。然后测试s
这将重复,直到正则表达式引擎在\n
之后到达t
:两个\n
匹配,并且$
断言位置字符串的结尾但在最后一行之前。 匹配,并进行替换。然后,字符串尚未完全解析,正则表达式引擎处理字符串,并匹配剩余的单个换行符,$
现在断言字符串最末端的位置 - >其他匹配和替换发生。由于正则表达式只在字符串末尾声明了位置,但没有使用它,并且正则表达式\n{0,2}$
可以匹配空字符串,因此存在第3个匹配并替换操作。
\n{1,2}\z
- (MINE) - 找到前2个\n
但字符串位置的最后一个不是,失败。然后重复相同的情况。然后检查\ns
并\n
通过测试(因为\n{1,2}
可以匹配一个\n
),但是没有字符串的结尾。这样,引擎在\n
之后达到t
。 2个\n
匹配,但在最终换行符之前没有字符串的最后一端,因此我们在这里失败了。下一场比赛是成功的,因为有两个\n
并且没有任何内容。
答案 1 :(得分:-1)
保持简单是一门艺术,永远不会成为一门科学。简单性很轻(相对于重量级和重量级)......它也违背了逻辑,因为它没有更多的东西显示而不仅仅是它自己:简单;-)下面的代码遵循简洁之路......而且它也是如此它也是......但是;不是那种令人讨厌的方式......只有你(以及机器)理解的简单方法......
<?php
$subject = "\n\n\nsubject\n\n\n";
$count = 2;
# EXPECTS 2 LF REMOVED AND SURE ENOUGH: ONLY 2 REMOVED...
var_dump(preg_replace("#^\n{" . $count . "}#",null,$subject));
# EXPECTS 2 LF REMOVED AND AGAIN, INDEED: ONLY 2 REMOVED...
var_dump(preg_replace("#\n{" . $count . "}\$#",null,$subject));