2014-02-12 53 views
-1

我想知道什麼正則表達式字符串可以用來解析python字符串。經過多次失敗,我來到了一個正則表達式的代碼,它可以分析最常用的字符串格式中的一種,像python字符串的正則表達式版本

"this is \"my string\", which ends here" 

這是我的regex-「代碼」:

"([^"\\]|(\\.))*" 

我問這個問題因爲我以前在互聯網上沒有發現過類似的東西。我可以使用該表達式並「開發」它來解析各種python字符串嗎?如果你發現這個問題很有趣,並且你可以很快檢查你的表達式。

+0

http://stackoverflow.com/questions/14366401/correctly-parsing-string-literals-with-pythons -re-module – thebjorn

+0

'r'「(?:\\」| [^「])*」''' –

+0

不要忘記,您還需要處理前綴(unicode/raw strings。)例如,u「ª unicode字符串「,r」\我有3個字面反斜槓\\「,UR'unícode和no \ e \ s \ c \ a \ p \ e字符'。還有分隔符 - '/「/'''/」「」。即使您不能在原始字符串中轉義分隔符,仍然無法使用反斜槓結束原始字符串。大量的邊緣案件涉及你想做的事情。 – GVH

回答

2

如果在報價前反斜槓奇數> 1你的正則表達式(和一個在@thebjorn鏈接)會失敗,我建議你使用這個模式(與單線模式):

"(?:[^"\\]|\\{2}|\\.)*" 

優化的方式:

"(?:(?=([^"\\]+|\\{2}|\\.))\1)*" 

處理單引號太:

(["'])(?:[^"'\\]|\\{2}|\\.|(?!\1)["'])*\1 

(["'])(?:(?=([^"'\\]+|\\{2}|\\.|(?!\1)["']))\2)*\1 

(注意4種模式的最後一個字符是完全在同一條線上,一個標誌?)

2

這是一種不同的方式,它使用tokenize.generate_tokens識別Python字符串。標記化模塊使用正則表達式;所以通過使用tokenize,您可以將複雜的骯髒工作留給Python本身。通過使用更高級別的函數,您可以更正確地使用正則表達式(並避免重新發明輪子)。此外,這可以正確識別各種Python字符串(例如單引號,雙引號和三引號類型的字符串),而不會被註釋混淆。

import tokenize 
import token 
import io 
import collections 

class Token(collections.namedtuple('Token', 'num val start end line')): 
    @property 
    def name(self): 
     return token.tok_name[self.num] 

text = r'''foo = 1 "this is \"my string\", which ends here" bar''' 

for tok in tokenize.generate_tokens(io.BytesIO(text).readline): 
    tok = Token(*tok)   # 1 
    if tok.name == 'STRING':  # 2 
     print(tok.val) 
  1. tokenize.generate_tokens返回元組。令牌類允許你 以更好的方式訪問元組中的信息。
  2. 特別是,每個令牌都有一個名稱,如'STRING','NEWLINE', 'INDENT'或'OP'。你可以用它來識別Python字符串。

編輯:我喜歡使用令牌類,所以我沒有寫 token.tok_name[num]在很多地方。然而,對於上面的代碼,它可能是更清晰,更容易忘記Token類和只寫中心思想明確:

import tokenize 
import token 
import io 

text = r'''foo = 1 "this is \"my string\", which ends here" bar''' 

for num, val, start, end, line in tokenize.generate_tokens(io.BytesIO(text).readline): 
    if token.tok_name[num] == 'STRING': 
     print(val) 
+0

它看起來非常技術性和優秀,但確實非常複雜,形式和我一樣新。 ---'Token(* tok)'你說'Token類允許你以更好的方式訪問元組中的信息。「對我來說不是很清楚。 - 我已將此答案加入書籤,以進一步探索。感謝您添加此答案。 –

+0

爲什麼'Token'類?只是'Token = collections.namedtuple('Token','num val start end line')'然後'tok = Token._make(tok)'會做...(除非我失去了一些東西) –

+0

@JonClements:在較長的代碼中,我不喜歡在整個地方寫'token.tok_name [num]'。用「name」屬性替換它是Token類的用途。 – unutbu