preg_replace 仅删除超过 2 行

preg_replace that only removes more than 2 lines

我需要使用 preg_replace 命令 只删除超过 2 行 。但是我的代码删除了所有行。我正在使用:

$content = preg_replace("/\r\n/", "\n", $_POST['content']);

输入:

Line1
Line2

Line3



Line4

输出:

Line1
Line2
Line3
Line4

我要:

Line1
Line2

Line3

Line4

所以代码必须只删除文本中多余的行。我可以使用不同类型的代码。

您可以使用:

echo preg_replace('/(\R)(\R){2,}/', "", $str);

Demo & explanation

用其中的两个替换其中的三个或更多:

... = preg_replace('/((\R))+/', '', ...);

在哪里

  • \R是什么构成了一行(换行符)
  • (\R)one
  • 的子模式
  • ((\R))two of one 通过反向引用的子模式并捕获替换
  • +one 中的一个或多个,通过反向引用

这使得一个中的三个或更多替换为一个中的两个。

比较:将其中的两个或多个替换为其中的一个,因为它更简单一些(and exists for reference already):

... = preg_replace('/(\R)+/', '', ...);

特别是在你的问题的上下文中:

将后面跟一个或多个 line-break/s 的两个换行符替换为前两个换行符,因为任何换行符都可能不同:

... = preg_replace('/(\R\R)\R+/', '', ...);

理由:

But my code removes all the lines.

... = preg_replace("/\r\n/", "\n", ...);

是的,它可能看起来是这样,但它实际上用换行符(LF;\n)替换了每个 Carriage-Return + Line-Feed(CRLF;\r\n)。

因此它删除了所有 Carriage-Return-s (CR; \r) 并保留 Line-Feed-s (LF; \n).

这只是为了更好地理解您的问题。重要的学习是你绝对不想用字符串 "\n" 替换,因为它 - 你的写法 - "removes all the lines".

解决这个问题的方法是你想用 "\r\n" 替换你在你的模式中引用的有根据的猜测。

其余类似本题:

  • PHP Preg-Replace more than one underscore

建议这样的模式:

... = preg_replace('/__+/', '_', ...);
# or:
... = preg_replace('/(_)+/', '', ...);

但要更换两个或更多。您想更换三个或两个以上连续入住。

根据先前假设用 "\r\n" (CRLF) 替换,这将是用其中两个替换三个或更多:

... = preg_replace('/\r\n\r\n(\r\n)+/', "\r\n\r\n", ...);
# or:
... = preg_replace('/(\r\n)+/', '', ...);

在您的变体中,新行由两个字符(CR 和 LF)组成,要替换的“字符”实际上是 sub-pattern(由括号构成)。

使用反向引用扩展最后一个示例,使其更符合参考问题中的 to 或 more 情况:

 ... = preg_replace('/(\r\n)+/', '', ...);

然后创建另一个反向引用以替换为您想要用两个替换三个或更多:

 ... = preg_replace('/((\r\n))+/', '', ...);

现在回到开头,在你的主题中,什么实际上构成了一个新行仍然不清楚,仍然有可能不是“\r\n”,而是其他变体(例如每个单独的“\r" 或 "\n") 可能是这样。由于处理行在正则表达式中很常见,幸运的是有一个专用的 escape-sequence 用于所有这些:

\R

line break: matches \n, \r and \r\n

(此描述为摘要)

使用 \R 而不是 (\r\n) 使模式:

 ... = preg_replace('/(\R{2})\R+/', '', ...);
 # or:
 ... = preg_replace('/((\R))+/', '', ...);