用其中两个替换三个或多个一个:
... = preg_replace('/((\R)\2)\2+/', '\1', ...);
在哪里
-
\R 构成一行(换行符)
-
(\R) 是 one 的子模式
-
((\R)\2) 是 two of one 的子模式,通过反向引用捕获替换
-
\2+ 是一个或多个 one 通过反向引用
这使得 one 中的三个或更多替换为 one 中的两个。
比较:用一个替换两个或多个一个,因为它更简单一些(and exists for reference already):
... = preg_replace('/(\R)\1+/', '\1', ...);
特别是在您的问题的背景下:
将后跟一个或多个换行符的两个换行符替换为前两个换行符,因为任何换行符都可能不同:
... = preg_replace('/(\R\R)\R+/', '\1', ...);
理由:
但我的代码删除了所有行。
... = preg_replace("/\r\n/", "\n", ...);
是的,它可能看起来如此,但它实际上将每个 Carriage-Return + Line-Feed (CRLF; \r\n) 替换为换行符 (LF; \n)。
因此,它删除了所有回车符(CR;\r)并保留换行符(LF;\n)。
这只是为了更好地理解您的问题。重要的学习是你绝对不想用字符串"\n" 替换它 - 你如何写 - “删除所有行”。
然后,解决这个问题的方法是在您引用模式中的那些时,您想用 "\r\n" 替换有根据的猜测。
剩下的和这个问题差不多:
这表明了这样的模式:
... = preg_replace('/__+/', '_', ...);
# or:
... = preg_replace('/(_)\1+/', '\1', ...);
但是要替换两个或更多。您想将三个或更多替换为两个连续留下。
使用前面的假设替换为"\r\n" (CRLF),这将是用其中的两个替换其中的三个或更多:
... = preg_replace('/\r\n\r\n(\r\n)+/', "\r\n\r\n", ...);
# or:
... = preg_replace('/(\r\n)\1\1+/', '\1\1', ...);
在您的变体中,新行由两个字符(CR 和 LF)组成,要替换的“字符”实际上是 sub-pattern(由括号构成)。
使用反向引用扩展最后一个示例,使其更符合引用问题中的 to 或 more 情况:
... = preg_replace('/(\r\n)\1\1+/', '\1\1', ...);
然后创建另一个反向引用来替换,因为你想用两个替换三个或更多:
... = preg_replace('/((\r\n)\2)\2+/', '\1', ...);
现在回到开头,仍然不清楚在您的主题中实际上什么构成了新行,但仍有可能不是“\r\n”而是其他变体(例如每个单独的“\r”或“ \n") 可能是这样。由于使用正则表达式处理行很常见,幸运的是有一个专用的escape-sequence 来处理所有这些:
\R
line break: matches \n, \r and \r\n
(此描述为摘要)
使用\R 代替(\r\n) 来生成模式:
... = preg_replace('/(\R{2})\R+/', '\1', ...);
# or:
... = preg_replace('/((\R)\2)\2+/', '\1', ...);