![](/img/trans.png)
[英]Unicode Regular Expression: Compilation failed: range out of order in character class
[英]Find out the position where a regular expression failed
我正在嘗試用JavaScript編寫一個詞法分析器來查找一個簡單的特定於域的語言的標記。 我從一個簡單的實現開始,它只是嘗試匹配一行中當前位置的后續regexp,以確定它是否與某些令牌格式匹配並接受它。
問題是,當這樣的正則表達式中的某些內容不匹配時,整個正則表達式失敗,所以我不知道哪個字符確實導致它失敗。
有沒有辦法找出字符串中導致正則表達式失敗的位置?
INB4:我不是在調試我的正則表達式並驗證它的正確性。 它已經正確,匹配正確的字符串並刪除不正確的字符串。 我只想以編程方式了解正則表達式停止匹配的位置,找出用戶輸入中不正確的字符的位置,以及它們中有多少是正常的。
有沒有辦法用簡單的正則表達式來實現它,而不是繼續實現一個完整的有限狀態自動機?
簡短的回答
沒有“字符串中的位置導致正則表達式失敗”。
但是,我將向您展示一個回答相反問題的方法:
正則表達式中的哪個令牌導致引擎無法匹配字符串?
討論
在我看來, the position in the string which caused the regular expression to fail
中the 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+$))?.
這里發生了什么? 每個前瞻在最后一個上逐步構建,一次添加一個令牌。 因此我們可以分別測試每個令牌。 最后的點是可選擇的視覺反饋:我們可以在調試器中看到至少有一個字符匹配,但我們不關心該字符,我們只關心捕獲組。
\\w+
令牌 \\w+\\d+
,因此,逐步測試\\d+
標記 \\w+\\d+$
,因此,逐步測試$
token 有三個捕獲組。 如果設置了所有三個,則匹配完全成功。 如果沒有設置第3組(與abc123a
),你可以說$
導致失敗。 如果組1已設置但未設置為組2(與abc
),則可以說\\d+
導致失敗。
供參考:故障路徑的內部視圖
對於它的價值,這里是RegexBuddy調試器的故障路徑視圖。
您可以使用否定字符集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/
。 雖然每個單詞都會單獨匹配,但整個表達式都會失敗。 你不知道Hello
或World
是否匹配 - 獨立,兩者都有。 它們之間的空白也是可用的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.