如何从PHP中删除文本中的空白行?

Sto*_*art 33 php regex

我需要在PHP中删除空白行(用空格或绝对空白).我使用这个正则表达式,但它不起作用:

$str = ereg_replace('^[ \t]*$\r?\n', '', $str);
$str = preg_replace('^[ \t]*$\r?\n', '', $str);
Run Code Online (Sandbox Code Playgroud)

我想要的结果:

blahblah

blahblah

   adsa 


sad asdasd
Run Code Online (Sandbox Code Playgroud)

将:

blahblah
blahblah
   adsa 
sad asdasd
Run Code Online (Sandbox Code Playgroud)

Mic*_*les 78

// New line is required to split non-blank lines
preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $string);
Run Code Online (Sandbox Code Playgroud)

上面的正则表达式说:

/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/
    1st Capturing group (^[\r\n]*|[\r\n]+)
        1st Alternative: ^[\r\n]*
        ^ assert position at start of the string
            [\r\n]* match a single character present in the list below
                Quantifier: Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
                \r matches a carriage return (ASCII 13)
                \n matches a fine-feed (newline) character (ASCII 10)
        2nd Alternative: [\r\n]+
            [\r\n]+ match a single character present in the list below
            Quantifier: Between one and unlimited times, as many times as possible, giving back as needed [greedy]
            \r matches a carriage return (ASCII 13)
            \n matches a fine-feed (newline) character (ASCII 10)
    [\s\t]* match a single character present in the list below
        Quantifier: Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
        \s match any white space character [\r\n\t\f ]
        \tTab (ASCII 9)
    [\r\n]+ match a single character present in the list below
        Quantifier: Between one and unlimited times, as many times as possible, giving back as needed [greedy]
        \r matches a carriage return (ASCII 13)
        \n matches a fine-feed (newline) character (ASCII 10)
Run Code Online (Sandbox Code Playgroud)

  • return preg_replace("/(^ [\ r \n]*| [\ r \n] +)[\ s\t]*[\ r \n] + /","\n",$ string); 这项工作 (6认同)
  • 使用http://regex101.com/生成示例中包含的说明. (6认同)
  • 你能准确解释一下正则表达式的作用吗?我不喜欢使用我一无所知的代码。 (2认同)

Ala*_*ore 25

您的ereg-replace()解决方案是错误的,因为这些ereg/eregi方法已被弃用.你preg_replace()甚至不会编译,但如果添加分隔符并设置多行模式,它将正常工作:

$str = preg_replace('/^[ \t]*[\r\n]+/m', '', $str);
Run Code Online (Sandbox Code Playgroud)

m修改允许^一个逻辑行的开头匹配,而不是整个字符串的仅仅是个开始.起始线锚是必要的,因为如果没有它,正则表达式将匹配每行末尾的换行符,而不仅仅是空行换行符.你不需要行结束锚($),因为你正在积极匹配换行符,但它没有受到伤害.

接受的答案能够完成任务,但它的复杂得多,它需要的.正则表达式必须匹配字符串的开头(^[\r\n]*未设置多行模式)或至少一个换行符([\r\n]+),后跟至少一个换行符([\r\n]+).因此,在以一个或多个空行开头的字符串的特殊情况下,它们将被替换为一个空行.我很确定这不是理想的结果.

但它在大多数情况下所做的是用一个换行符替换两个或多个连续的换行符,以及位于它们之间的任何水平空格(空格或制表符).无论如何,那是意图.作者似乎希望\s只匹配空格字符(\x20),实际上它匹配任何空格字符.这是一个非常常见的错误.实际列表从一种正则表达式的风格到下一种不同,但至少你可以期望\s匹配任何[ \t\f\r\n]匹配.

实际上,在PHP中你有一个更好的选择:

$str = preg_replace('/^\h*\v+/m', '', $str);
Run Code Online (Sandbox Code Playgroud)

\h匹配任何水平空格字符,并\v匹配垂直空格.


Ben*_*Ben 12

只需将文本行array_filter分解为数组,删除空行并再次内爆数组.

$tmp = explode("\n", $str);
$tmp = array_filter($tmp);
$str = implode("\n", $tmp);
Run Code Online (Sandbox Code Playgroud)

或者在一行中:

$str = implode("\n", array_filter(explode("\n", $str)));
Run Code Online (Sandbox Code Playgroud)

我不知道,但这可能比快preg_replace.


Dan*_*wer 6

从Bythos评论上述从杰米的链接为我工作:

/^\n+|^[\t\s]*\n+/m
Run Code Online (Sandbox Code Playgroud)

我不想剥离所有新行,只是空/空白行.这就是诀窍!


小智 5

没有必要把事情搞得太复杂。这可以通过一个简单的短正则表达式来实现:

$text = preg_replace("/(\R){2,}/", "$1", $text);
Run Code Online (Sandbox Code Playgroud)

匹配(\R)所有换行符。
匹配{2,}两次或多次出现。
使用$1第一个反向引用(特定于平台的 EOL)作为替换。


hak*_*kre 5

这个问题很久以前就已经得到了回答,但可以大大受益于preg_replace简化的模式:

$result = preg_replace('/\s*($|\n)/', '\1', $subject);
Run Code Online (Sandbox Code Playgroud)

模式:删除换行符之前的所有空格 - 或字符串末尾的 - 。

最长的比赛获胜:

  • 由于空白\s具有贪婪量词*并且包含\n连续的空行,因此会被匹配。

  • \scontains\r一样,\r\n支持换行序列,但不支持单行序列\r(不带)。\n

  • $匹配缓冲区的末尾时,反向引用\1为空,也允许处理末尾的尾随空白。

如果还需要删除前导(空)行,则它们也必须在不捕获时匹配(这不是直接要求的,但可能是合适的):

$result = preg_replace('/^(?:\s*\n)+|\s*($|\n)/', '\1', $subject);
#                        '----------'
Run Code Online (Sandbox Code Playgroud)

模式:同时删除所有前导空白(第一行为空)。

如果缓冲区末尾的换行符应该以不同的方式规范化(始终在末尾换行而不是从不),则需要添加:. "\n"

此变体可移植到\r\n\r\n换行序列 ( (?>\r\n|\r|\n)) 或\R

$result = preg_replace('/^(?> |\t|\r\n|\r|\n)+|(?> |\t|\r\n|\r|\n)*($|(?>\r\n|\r|\n))/', '\1', $subject);
# or:
$result = preg_replace('/^(?:\s*\R)+|\s*($|\R)/', '\1', $subject);
Run Code Online (Sandbox Code Playgroud)

模式:支持所有换行序列。

这样做的缺点是新行无法标准化(例如,三个 to 中的任何一个\n)。

因此,在删除之前标准化换行符是有意义的:

$result = preg_replace(['/(?>\r\n|\n|\r)/', '/\s*($|\n)/'], ["\n", '\1'], $subject);
# or:
$result = preg_replace(['/\R/u', '/\s*($|\n)/'], ["\n", '\1'], $subject);
Run Code Online (Sandbox Code Playgroud)

除了线路处理之外,它还提供了进行一些标准化的机会。

例如,删除尾随空白并修复文件末尾丢失的换行符。

然后进行更高级的行标准化,例如在开头和结尾处清零空行;否则不超过两个连续的空行:

$result = preg_replace(
    ['/[ \t]*($|\R)/u', '/^\n*|(\n)\n*$|(\n{3})\n+/'], 
    ["\n"             , '\1\2'                      ], 
    $subject
);
Run Code Online (Sandbox Code Playgroud)

次要模式已经从第一个模式替换中受益。

这里的力量preg_replace依赖于明智地选择要替换的反向引用。

使用多种模式还可以大大简化事情并保持流程的可维护性。