2009-07-30 360 views
3

我一直在摔跤我正在希望用正則表達式解決的問題。正則表達式除去括號之間的所有空格

比方說,我有一個字符串,可以包含任何字母數字,並且可能包含方括號內的子字符串。這些子字符串可以像這樣出現在字符串中的任何位置。也可以有任意數量的括號子字符串。

實例:

  • AAA [BB B]
  • AAA [BBB] CCC [d DD]
  • [AAA] BBB並[c CC]

可以看到在一些括號內的子字符串中有空格,沒關係。我的主要問題,現在的問題是,當我遇到空間這樣的支架之外:

  • 一節AA [BB B]

現在我要保留括號內的空間,但在其他地方刪除。

這就會變得稍微有點棘手像字符串:

  • 一節AA [BB B](閉杯)[d DD]éEE [F FF]

在這裏,我想回報爲:

  • AAA [BB b] CCC [d DD] EEE [F FF]

我花了一些現在可以通過關於lookaround,negative assertions等不同章節的不同閱讀方式閱讀這些內容,並且它讓我的頭腦旋轉起來。

注意:對於訪問此的任何人,我沒有尋找任何涉及嵌套括號的解決方案。如果是這種情況,我可能會像下面提到的一些評論一樣務實地做。

回答

10

此正則表達式應該做的伎倆:

[ ](?=[^\]]*?(?:\[|$)) 

只需更換這與「」相匹配的空間。

基本上它所做的一切都是確保你要刪除的空間在它前面有一個「[」,但如果它之前有一個「]」,則不會。

只要你沒有嵌套的方括號,例如,這應該工作:

AA [B [CC] B]

因爲在這種情況下,之後的第一個 「B」 的空間將被刪除,它將成爲:

AA [b [CC] b]

+1

+1回答實際的問題:如何執行*這個任務*(即沒有嵌套)*用正則表達式*。 – 2009-07-31 02:42:10

+0

太棒了,謝謝。我有點接近,但我無法處理過去兩套括號內的子串。我不需要嵌套括號(phew!)。 – seano 2009-07-31 13:48:00

+1

的「| $」末需要的情況下,你的字符串是像「一節AA [BB B](閉杯)[d DD]éEE [F FF; G GG」,擺脫之間的空間的克氏。他們沒有跟隨他們,所以你也想檢查字符串的結尾('$')。你是對的,第一個字符類中的'[''不是必需的。這是因爲'。*?b'基本上與'[^ b] * b'相同,只要這是正則表達式的結尾。在我使用'?'之前,這只是我在寫作時留下的。字符。但有趣的是,'。+?b'與'[^ b] + b'不同。 – Senseful 2009-07-31 15:29:38

8

這聽起來並不像你真正想要的正則表達式的東西。通過閱讀直接解析非常容易。僞代碼:

inside_brackets = false; 
for (i = 0; i < length(str); i++) { 
    if (str[i] == '[') 
     inside_brackets = true; 
    else if str[i] == ']' 
     inside_brackets = false; 
    if (! inside_brackets && is_space(str[i])) 
     delete(str[i]); 
} 

任何涉及正則表達式是要涉及大量的回顧後的東西,這將是一遍又一遍地重複,它會慢得多和少理解。

要使嵌套括號適用此工作,只需將inside_brackets更改爲計數器,從零開始,在打開的括號上遞增並在近括號內遞減。

1

如何做到這一點取決於什麼應該做:

a b [ c [ d [ e ] f ] g 

這是不明確的;可能的答案是至少:

  • ab[ c [ d [ e ] f ]g
  • ab[ c [ d [ e ]f]g
  • 誤差出來;括號不匹配!

對於前兩種情況下,你可以使用正則表達式。對於第三種情況,使用(小)解析器會更好。

對於任一種情況下一個或兩個,劃分在第一[的字符串。從[之前一切地帶空間(這顯然括號外)。接下來,尋找.*\](情況1)或.*?\](案例2)並移動到你的輸出。重複,直到你沒有輸入。

2

這個工作對我來說:

(\[.+?\])|\s 

然後你只需傳遞$ 1的重置價值,當你調用替換功能。這個想法是首先查找括號內的模式,並確保它們未被觸摸。然後括號外的所有空間都被替換爲空。

請注意,我用正則表達式英雄(一個.NET正則表達式測試儀),而不是在PHP中測試這一點。所以我不是100%肯定這會適合你。

這是一個有趣的一個。聽起來很簡單,然後看起來相當困難。然後我終於到達的解決方案確實很簡單。我很驚訝這個解決方案不需要查看任何形式的內容。它應該比使用lookaround的任何方法都快。

0

以下內容將匹配行首或括號末尾(必須出現在您想要匹配的任何空格之前),後面跟着任何不是開始括號或空格的字符,後跟一些空間。

/((^|\])[^ \[]*) +/ 

$1取代「所有」將從每個非括號序列去除的空間的第一個塊。您將不得不重複該比賽以刪除所有空格。

例子:

abcd efg [hij klm]nop qrst u 
abcdefg [hij klm]nopqrst u 
abcdefg[hij klm]nopqrstu 
done 
0

復活這個問題,因爲它有這樣的沒有提到一個簡單的解決方案。

\[[^]]*\](*SKIP)(*F)|\s+ 

交替的左側匹配完整的括號組然後故意失敗。右側匹配和捕捉空間,以第1組,我們知道他們是正確的空格,因爲如果他們是括號內他們會一直未能在左邊的表達。

看到比賽在這個demo

這意味着你可以做

$replace = preg_replace("~\[[^]]*\](*SKIP)(*F)|\s+~","",$string); 

參考

  1. How to match pattern except in situations s1, s2, s3
  2. How to match a pattern unless...
相關問題