2013-11-21 57 views
2

我想下面的字符串轉換Python的正則表達式 - 匹配的字符不消耗它

"For "The" Win","Way "To" Go"

"For ""The"" Win","Way ""To"" Go"

直截了當的正則表達式將是

str2 = re.sub(r'(?<!,|^)"(?=\w)|(?<=\w)"(?!,|$)', '""', str1,flags=re.MULTILINE) 

ie,雙引號tha噸是

  1. 後跟一個字母而不是用逗號或行的開始之前
  2. 用字母在之前但不跟一個逗號或行尾

的問題是我使用python,它的正則表達式引擎不允許在lookbehind構造中使用OR運算符。我得到的錯誤

sre_constants.error: look-behind requires fixed-width pattern

我所尋找的是一個正則表達式將與'""'取代'"'圍繞「的」和「要」。 我可以使用下面的正則表達式(提供給another question的回答)

\b\s*"(?!,|[ \t]*$) 

但在此之前的「的」和「要」只是佔用的空間,我得到了下面

"For""The"" Win","Way""To"" Go"

有沒有解決方法,以便我可以將「The」和「To」的引號加倍而不佔用前面的空格?

+0

對於這樣一個字符串:''「對於」mar「vel」ous Win「'',你是否想要改變名詞內的引號? – eyquem

回答

1
re.sub(r'\b(\s*)"(?!,|[ \t]*$)', r'\1""', s) 
+0

@SpikETidE因此,''(? eyquem

2

不要說沒有用逗號或行開始之前,說前面有一個非逗號字符:

r'(?<=[^,])"(?=\w)|(?<=\w)"(?!,|$)' 
+0

如果使用否定,那麼我想我必須找到所有可能的字符,我必須否定。例如: r'(?<= [^,\ n])「(?= \ w)|(?<= \ w)」(?!,| $)' – SpikETidE

+0

@SpikETidE,期望的輸出? – perreal

+1

@SpikETidE請將部分代碼放在兩個字符''的左邊,兩個字符放在它的右邊。點擊評論窗口右側的**幫助** – eyquem

1

大多數每當你遇到這個問題直接的解決方法:爆炸向後看成兩個後視鏡。

str2 = re.sub(r'(?<!,)(?<!^)"(?=\w)|(?<=\w)"(?!,|$)', '""', str1,flags=re.MULTILINE) 

(不命名你的字符串str

+0

@SpikETidE也許再試一次?我剛剛測試過,它工作正常。正如它應該的那樣 - 兩個向後看斷言在邏輯上是等價的。 – roippi

+0

@ roippi:對不起。我的測試字符串存在差異,導致測試失敗。我在發佈回覆之前刪除了我的評論。 – SpikETidE

0
str2 = re.sub('(?<=[^,])"(?=\w)' 
       '|' 
       '(?<=\w)"(?!,|$)', 

       '""', ss, 
       flags=re.MULTILINE) 

我一直想知道爲什麼人們使用正則表達式模式的原始字符串是不需要的時候。

注意我改變你的str這是一個內置類的名稱ss

對於` 「有趣」:

str2 = re.sub('"' 
       '(' 
       '(?<=[^,]")(?=\w)' 
       '|' 
       '(?<=\w")(?!,|$)' 
       ')', 

       '""', ss, 
       flags=re.MULTILINE) 

或也

str2 = re.sub('(?<=[^,]")(?=\w)' 
       '|' 
       '(?<=\w")(?!,|$)', 

       '"', ss, 
       flags=re.MULTILINE) 
+1

如果沒有'r',字符串將作爲普通字符串處理,並帶有字符串轉義字符。正則表達式中的某些轉義在非原始字符串文字中具有不同的含義(例如'\ 1'和'\ b')。不要根據是否使用這些字符串來調整字符串的「粗糙度」,而是總是將「r」放在正則表達式中比較容易。 –

+0

我知道,我知道。就個人而言,由於我使用的正則表達式對''1''和''\ b''的使用較少,因此我寧願不將「'r」放在我更頻繁使用的所有正則表達式模式之前,在必要時寫入''\\ 1 \\ 2''和''\\ b''。順便說一下,如果不是原始字符串,我們必須編寫''\\ b'',而''\ d \ w \ s etc''不需要這樣。我不記得是否有其他特殊的序列,而不是你所引用的序列,需要在非原始字符串中進行雙重裁剪或在原始字符串中正確工作。你做 ? – eyquem

+0

@Markus事實上,奇怪的是,還選擇了一個基於字母「b」的轉義字符串,以便像在正則表達式中一樣使用backspace來表示一個badary。那麼在非原始字符串正則表達式模式下生成等同於''''r'''和''''的原則不適用於''b''的轉義:在正則表達式模式,一個非原始字符串'''\ b'''表示一個退格符和'''\\ b'''爲非原始字符串模式或''r'\ b'''表示一個boudary。 – eyquem

2

在我看來就像你不需要用錨打擾。

  • 如果在引用之前有一個字符,那麼您知道它不在字符串的開頭。
  • 如果該字符不是換行符,那麼您不在行的開頭。
  • 如果角色不是逗號,那麼您並不處於某個字段的開頭。

所以你不需要使用錨,只是做了積極的回顧後/超前的單個字符:

result = re.sub(r'(?<=[^",\r\n])"(?=[^,"\r\n])', '""', subject) 

我在"扔在的機會,有可能是一些報價是已經逃脫。但實際上,如果是這種情況,你可能無論如何都會搞砸。 ;)

+0

唉,OP是那種等待良好答案的人,即使在問題寫錯問題時也是如此。在Markus答案中看到我的評論。 – eyquem

+0

這個解決方案的問題在於「」「」hourrah!「Win」''變成了''「對於」「」「」hourrah!「」Win「''而它應該變成」 ''「對於」「」hourrah!「贏」'';如果OP的問題中的條件'(?= \ w)'和'(?<= \ w)'是他想要的,我不確定。 – eyquem

+0

我想OP是限制他的想法,一個具體的例子,他需要逃避的引號總是碰巧在字母旁邊,而他正在讓這個細節進入他的方式。我的態度是,我們不是在這裏回答問題,以幫助人們找到正確的問題。但是,正如你在第一條評論中所看到的,並不是每個人都有同樣的感受。 –