我有這樣的正則表達式:爲什麼這個正則表達式匹配?
(?<!Sub).*\(.*\)
而且我想它來搭配這樣的:
MSGBOX(「總運行時間來修復區和TD領域是:」 & = imeElapsed &「分鐘「)
但不是這樣的:
子ChangeAreaTD()
但一些我怎麼仍然匹配以Sub開頭的那個...有沒有人有任何想法爲什麼?我以爲我會排除「子」做
(?<!Sub)
任何幫助表示讚賞!
謝謝。
我有這樣的正則表達式:爲什麼這個正則表達式匹配?
(?<!Sub).*\(.*\)
而且我想它來搭配這樣的:
MSGBOX(「總運行時間來修復區和TD領域是:」 & = imeElapsed &「分鐘「)
但不是這樣的:
子ChangeAreaTD()
但一些我怎麼仍然匹配以Sub開頭的那個...有沒有人有任何想法爲什麼?我以爲我會排除「子」做
(?<!Sub)
任何幫助表示讚賞!
謝謝。
您正則表達式(?<!Sub).*\(.*\)
,拆開:
(?<! # negative look-behind
Sub # the string "Sub " must not occur before the current position
) # end negative look-behind
.* # anything ~ matches up to the end of the string!
\( # a literal "(" ~ causes the regex to backtrack to the last "("
.* # anything ~ matches up to the end of the string again!
\) # a literal ")" ~ causes the regex to backtrack to the last ")"
所以,隨着您的測試字符串:
Sub ChangeAreaTD()
.*
之後移動到字符串末尾。.*
,後視從來沒有真正有所作爲。你很可能想的
(?<!Sub .*)\(.*\)
,但它是不太可能變長向後看是由你的正則表達式引擎支持。
所以我會做的是這個(因爲可變長度前瞻的廣泛支持):
^(?!.*\bSub\b)[^(]+\(([^)]+)\)
意爲:
^ # At the start of the string,
(?! # do a negative look-ahead:
.* # anything
\b # a word boundary
Sub # the string "Sub"
\b # another word bounday
) # end negative look-ahead. If not found,
[^(]+ # match anything except an opening paren ~ to prevent backtracking
\( # match a literal "("
( # match group 1
[^)]+ # match anything up to a closing paren ~ to prevent backtracking
) # end match group 1
\) # match a literal ")".
,然後去比賽的內容組012.
但是,正則表達式通常是嚴重不適合解析代碼。對於HTML而言,這與VB代碼的情況一樣。即使改進了正則表達式,你也會得到錯誤的匹配。例如,在這裏,因爲嵌套的父親:
MsgBox ("The total run time to fix all fields (AREA, TD) is: ...")
這樣做:
^MsgBox .*\(.*\)
的問題是負回顧後並不能保證一個字符串的開頭。它會匹配任何地方。
但是,在正則表達式的開頭添加一個^
字符確保字符串的開頭。然後,將Sub
更改爲MsgBox
,以便它只匹配以MsgBox
在這種情況下,後視沒有意義,因爲在字符串開始之前不能有任何東西。 – Gumbo 2010-07-15 16:26:25
嗯謝謝你我已經修復了它 – 2010-07-15 23:55:31
這會幫助我,如果我只是想抓住MsgBox調用,但我從原始問題中省略的一件事是,我實際上試圖抓取所有的方法調用,但沒有方法聲明。 所以我需要的是: <任何字符不是「Sub」>(<任何字符>) – 2010-07-16 09:19:31
開頭的字符串。這裏有一個回溯問題。 (?<!Sub).*\(.*\)
中的第一個.*
可以匹配ChangeAreaTD或hangeAreaTD。在後一種情況下,前4個字符是ub C
,與Sub
不匹配。當後視被否定時,這就相當於一場比賽!
只要將^
添加到您的正則表達式的開頭並不會對您有所幫助,因爲後視是零長度匹配短語。 ^(?<!MsgBox)
將尋找一條以MsgBox
結尾的行。你需要做的是^(?!Sub)(.*\(.*\))
。這可以解釋爲「從字符串的開頭開始,確保它不以Sub開頭,然後,如果它看起來像方法調用,則捕獲字符串中的所有內容」。
正則表達式引擎解析lookaround的一個很好的解釋可以找到here。
如果您只想匹配函數調用而不是聲明,那麼預括號匹配不應匹配任何字符,但更可能是任何標識符字符後跟空格。因此,
(?<!Sub)[a-zA-Z][a-zA-Z0-9_]* *\(.*\)
標識符可能需要更多的標記,具體取決於您匹配的語言。
哦,我明白了爲什麼現在失敗。你會推薦另一種解析代碼的方法嗎? 我用正則表達式去了,因爲我注意到關於VBA的一件事是每個定義總是隻有一行。與C#不同的是,例如,如果(())和下一行中的括號相同,則VBA始終將所有內容保留爲一行。 –
2010-07-16 09:22:45
@Tiago:這不完全正確。您可以在一行的末尾插入下劃線,並將其視爲續行。你可以用冒號分隔兩個邏輯代碼行('Dim x:x = 10')。對於解析語言,請始終使用解析器。不知道是否有一個解析器可以用來解析VB代碼,但不應該寫太難。不過,這是一個單獨問題的材料。 – Tomalak 2010-07-16 10:10:04
好悲傷..我不知道下劃線,或者說,我從VB .NET知道它,我只是不認爲它也適用於VBA。我只是查了一下,它和冒號一樣。 我想我最終會用'\ r \ n'替換冒號並刪除'_ \ r \ n'的所有實例,因爲下劃線必須是該行的最後一個字符。 我試過尋找一個VBA的解析器,似乎沒有一個,再加上我有大約三個月的時間想出創建一個抽象的語法樹出VBA代碼,然後生成C#出AST。 – 2010-07-16 11:16:24