2014-03-29 84 views
0

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

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.} 

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

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

那么如何用preg_replace做到这一点呢?

+0

'\ s'匹配的空白,不只是换行符。 – faintsignal

+0

@faintsignal是的,但在这种情况下,替换的形式是'preg_replace('#\ s +#','',$ str);'。所以它会保留它的空间。 – Vivendi

回答

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前添加一个负前瞻或回顾后(这是完全一样的,因为你是在处理零宽度断言)(?!\A)


如果你不”由themselve或该更换

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

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

其中大括号的部分(如您例如与领先的新行):约方括号,只有不在乎想跳过大括号中的内容,你可以做到这一点

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

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

其中相同部件被跳过,因为子模式被强制失败,(*FAIL)(*SKIP)禁止在同一位置重试子模式(当子模式失败时)。

1

说不上来,如果它比卡西米尔的正则表达式更有效,但这里是一个替代方法是也许有点比较容易让人接受:

$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.} 
+0

+1这是个好主意。通常,使用'preg_replace_callback'可以让模式(或方法)更容易(更快)写入。 –

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