簡體   English   中英

找出正則表達式失敗的位置

[英]Find out the position where a regular expression failed

我正在嘗試用JavaScript編寫一個詞法分析器來查找一個簡單的特定於域的語言的標記。 我從一個簡單的實現開始,它只是嘗試匹配一行中當前位置的后續regexp,以確定它是否與某些令牌格式匹配並接受它。

問題是,當這樣的正則表達式中的某些內容不匹配時,整個正則表達式失敗,所以我不知道哪個字符確實導致它失敗。

有沒有辦法找出字符串中導致正則表達式失敗的位置?

INB4:我不是在調試我的正則表達式並驗證它的正確性。 它已經正確,匹配正確的字符串並刪除不正確的字符串。 我只想以編程方式了解正則表達式停止匹配的位置,找出用戶輸入中不正確的字符的位置,以及它們中有多少是正常的。

有沒有辦法用簡單的正則表達式來實現它,而不是繼續實現一個完整的有限狀態自動機?

簡短的回答

沒有“字符串中的位置導致正則表達式失敗”。

但是,我將向您展示一個回答相反問題的方法:

正則表達式中的哪個令牌導致引擎無法匹配字符串?

討論

在我看來, the position in the string which caused the regular expression to failthe position in the string which caused the regular expression to fail問題是顛倒的。 當引擎向下移動字符串時左手和圖案右手,一個正則表達式匹配六個字符可以稍后,因為量詞和回溯,減少到匹配零字符下一個或擴展匹配十。

在我看來,一個更恰當的問題是:

正則表達式中的哪個令牌導致引擎無法匹配字符串?

例如,考慮正則表達式^\\w+\\d+$和字符串abc132z

\\w+實際上可以匹配整個字符串。 然而,整個正則表達式失敗了。 說正則表達式在字符串末尾失敗是否有意義? 我不這么認為。 考慮一下。

最初, \\w+將匹配abc132z 然后引擎前進到下一個標記: \\d+ 在這個階段,引擎在弦中回溯,逐漸讓\\w+放棄2z (這樣\\w+現在只對應於abc13 ),允許\\d+匹配2

在這個階段, $斷言在z離開時失敗。 引擎回溯,讓\\w+ ,放棄3字符,然后是1 (這樣\\w+現在只對應abc ),最終允許\\d+匹配132 在每一步,引擎都會嘗試$斷言並失敗。 根據引擎內部結構,可能會出現更多回溯: \\d+將再次放棄2和3,然后\\w+將放棄c和b。 當引擎最終放棄時, \\w+僅匹配初始a 你能說正則表達式“在”3“上失敗嗎?在”b“上?

不。如果您從左到右查看正則表達式模式,您可以認為它在$上失敗,因為它是我們無法添加到匹配中的第一個令牌。 請記住,還有其他方法可以證明這一點。

降低,我會給你一個截圖來形象化。 但首先,讓我們看看我們是否可以回答另一個問題。

其他問題

是否有技術可以讓我們回答另一個問題:

正則表達式中的哪個令牌導致引擎無法匹配字符串?

這取決於你的正則表達式。 如果您能夠將正則表達式切割成干凈的組件,那么您可以在捕獲組內部設計一系列可選的前瞻,從而使匹配始終成功。 第一個未設置的捕獲組是導致失敗的組。

Javascript在可選前瞻上有點吝嗇,但你可以這樣編寫:

^(?:(?=(\w+)))?(?:(?=(\w+\d+)))?(?:(?=(\w+\d+$)))?.

在PCRE,.NET,Python ......你可以更緊湊地寫這個:

^(?=(\w+))?(?=(\w+\d+))?(?=(\w+\d+$))?.

這里發生了什么? 每個前瞻在最后一個上逐步構建,一次添加一個令牌。 因此我們可以分別測試每個令牌。 最后的點是可選擇的視覺反饋:我們可以在調試器中看到至少有一個字符匹配,但我們不關心該字符,我們只關心捕獲組。

  1. 第1組測試\\w+令牌
  2. 第2組似乎測試\\w+\\d+ ,因此,逐步測試\\d+標記
  3. 第3組似乎測試\\w+\\d+$ ,因此,逐步測試$ token

有三個捕獲組。 如果設置了所有三個,則匹配完全成功。 如果沒有設置第3組(與abc123a ),你可以說$導致失敗。 如果組1已設置但未設置為組2(與abc ),則可以說\\d+導致失敗。

供參考:故障路徑的內部視圖

對於它的價值,這里是RegexBuddy調試器的故障路徑視圖。

RegexBuddy Debug

您可以使用否定字符集RegExp

 [^xyz] [^ac] 

否定或補充的字符集。 也就是說,它匹配括號中未包含的任何內容。 您可以使用連字符指定一系列字符,但如果連字符顯示為方括號中的第一個或最后一個字符,則將其視為字符連字符,作為普通字符包含在字符集中。

String.prototype.match() index屬性

返回的Array有一個額外的input屬性,它包含已解析的原始字符串。 此外,它還有一個index屬性,表示字符串中匹配的從零開始的索引。

例如,在字符串aBcD7zYx記錄RegExp /[^a-zA-z]/匹配數字的index

 var re = /[^a-zA-Z]/; var str = "aBcD7zYx"; var i = str.match(re).index; console.log(i); // 4 

有沒有辦法找出字符串中導致正則表達式失敗的位置?

不,沒有。 正則表達式匹配或不匹配。 介於兩者之間。

部分表達式可以匹配,但整個模式不會。 所以引擎總是需要評估整個表達式:

拿String Hello my World和Pattern /Hello World/ 雖然每個單詞都會單獨匹配,但整個表達式都會失敗。 你不知道HelloWorld是否匹配 - 獨立,兩者都有。 它們之間的空白也是可用的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM