替换部分字符串中的换行符

时间:2014-03-29 20:06:58

标签: php regex preg-replace

我想在字符串的一部分中替换换行符。假设我有以下内容:

foo bar __level [
$save = 123,
Info = '1234'
]
{Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut 
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco 
laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate 
velit esse cillum dolore eu fugiat nulla pariatur.}

我想将其替换为:

foo bar __level [$save = 123,Info = '1234']
{Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut 
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco 
laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate 
velit esse cillum dolore eu fugiat nulla pariatur.}

所以基本上应该删除新行,直到它看到{个字符。其余的应该保持新的界限。

我知道我可以用preg_replace \s+替换所有换行符。但是我不知道在这种情况下该怎么做,因为我只需要将它替换为字符串中的一小部分。

那么如何使用preg_replace

来完成

3 个答案:

答案 0 :(得分:1)

假设所有方括号都是平衡的而不是嵌套的,您可以使用以下代码:

$pattern = '~(?:\[|(?!\A)\G)[^]\r\n]*\K\R+~';

$txt = preg_replace($pattern, '', $txt);

模式细节:

(?:           # open a non capturing group
    \[        # a literal opening square bracket
  |           # or
    (?!\A)\G  # the position in the string after the last match
)             # close the non capturing group
[^]\r\n]*     # zero or more characters that are not ] or CR or LF
\K            # resets all from match result
\R+           # any type of newline one or more times

上面的模式假设总是有一个结束方括号,如果缺少结束方括号,则处理开始方括号之后的所有文本直到字符串结尾。

如果要更改此行为,则必须添加前瞻断言以检查是否存在结束方括号(但请注意,这会使模式变慢):

(?:\[|(?!\A)\G)[^]\r\n]*\K\R+(?=[^]]*])

关于\G
这是一个锚点(^ $ \A \z是),表示最后一次匹配后字符串中的位置,但是因为在开始时没有最后一个匹配,\G设置为字符串的开头(\A^)。为了避免这种情况,一种方法是在\G 之后或之前添加负向前瞻或后观(由于您处理零宽度断言,这是完全相同的):{{1 }}


如果您不关心方括号,只想跳过大括号之间的内容,可以这样做:

(?!\A)

其中大括号部分(如示例中的前导换行符)被替换为selfsel或this:

$pattern = '~(\R?\h*{[^}]*})|\R+~';

$txt = preg_replace($pattern, '$1', $txt); 

跳过相同的部分,因为子模式被强制失败,$pattern = '~\R?\h*{[^}]*}(*SKIP)(*FAIL)|\R+~'; $txt = preg_replace($pattern, '', $txt); (*FAIL)禁止在相同位置重试子模式(当子模式失败时)。

答案 1 :(得分:1)

Dunno,如果它比卡西米尔的正则表达式效率更高,但这是一种可能更容易吞下的替代方法:

$content = <<<'EOC'
foo bar __level [
$save = 123,
Info = '1234'
]
{Lorem ipsum dolor sit 
amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut 
labore et dolore magna aliqua. 
Ut enim ad minim veniam, quis nostrud exercitation ullamco 
laboris nisi ut aliquip 
ex ea commodo consequat. Duis aute irure dolor in 
reprehenderit in voluptate 
velit esse cillum dolore eu fugiat nulla pariatur.}
EOC;

$content = preg_replace_callback(
  '~^([^{]*)~',
  function ($m) {
    return str_replace(array("\r","\n"),'',$m[1]);
  },
  $content
);

echo "<pre>".$content;

<强>输出:

foo bar __level [$save = 123,Info = '1234']{Lorem ipsum dolor sit 
amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut 
labore et dolore magna aliqua. 
Ut enim ad minim veniam, quis nostrud exercitation ullamco 
laboris nisi ut aliquip 
ex ea commodo consequat. Duis aute irure dolor in 
reprehenderit in voluptate 
velit esse cillum dolore eu fugiat nulla pariatur.}

答案 2 :(得分:0)

简单模式:

(?=\R)\R+(?=.*\R{)

说明

(?=         # a Positive Lookahead
    \R      # for a new line
)           # Lookahead end
    \R+     # match the new line(s)
(?=         # another Positive Lookahead
    .*      # match every character until
    \R      # another new line
    {       # followed by a curly bracket
)           # Lookahead end

使用:

$string = preg_replace("/(?=\R)\R+(?=.*\R{)/s", "", $string);

<强> Live regex demo

<强> Live PHP demo