2014-03-29 82 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