2012-07-21 51 views
2

是否可以輸出導致與正則表達式不匹配的字符串(其索引)中的第一個字符?僅僅使用正則表達式匹配操作是可能的還是必須使用更復雜的東西?輸出導致與正則表達式不匹配的第一個字符

例如,在JavaScript中,我可能有一個正則表達式/^\d{3}\s\d{2}$/,該字符串與3位數字後跟空格和另一個2位數字匹配。我有一個字符串"123a45"我應用這個正則表達式。由於正則表達式不匹配,因此執行此操作(例如,"123a45".match(/^\d{3}\s\d{2}$/))將返回null。我怎樣才能得到導致這種不匹配的第一個字符(在這種情況下,"a",索引爲3的字符)?

這樣做的一個用例可能是直接指向用戶根據用於驗證的正則表達式導致用戶輸入的字符串無效的字符。

+4

廣義問題很可能不可行(一個例子是使用OR'|'的正則表達式,因爲有2種可能的情況,您不知道哪個字符實際上導致了問題)。對於某些特定的問題,在某種程度上可能是可能的。 – nhahtdh 2012-07-21 20:02:54

+0

難道你不知道當匹配失敗時用'|'表示哪個部分? – 2012-07-21 20:17:40

+0

例如:'([A-Z] [0-9] {2} | [0-9] {2} [A-Z])'並輸入'090',你會報告哪個字符?第一個「0」還是最後一個「0」?正如所指出的那樣,匹配失敗是因爲它不符合'OR'指定的所有情況,並且原因可能會有所不同。 – nhahtdh 2012-07-21 20:20:55

回答

3

您需要將正則表達式分解爲部分匹配的所有可能的匹配模式,以及從最長匹配到最短匹配(或無)的排序模式列表。一旦你得到了匹配,計算(部分)匹配的長度,你會得到導致不匹配的角色位置。來自該位置的具有一個字符長度的子字符串正是該不匹配背後的字符(如果有的話)。如果沒有不匹配,則返回空(子)字符串。

var s = "123a45"; 
alert(s.substr(s.match(/^(\d{3}\s\d{2}|\d{3}\s\d|\d{3}\s|\d{0,3})/)[1].length,1)); 

http://jsfiddle.net/ETWWS/

+1

謹慎添加一個簡短的解釋? – 2012-07-21 19:58:58

+0

您認爲這是一種可以應用於各種正則表達式的通用解決方案嗎?你認爲你可以自動生成包含所有部分匹配正則表達式的「擴展」正則表達式嗎? – 2012-07-21 20:13:48

+1

@jindrichm - 每個固定長度的非替代模式都可以分解。所以下面的例子不能:(1)'\ d {2,4}:\ d {1,2}',(2)'(\ w {3} \ d {2} | \ d {3} \ w {2})'等。 – 2012-07-21 20:16:25

2

提供詳細的解釋了爲什麼輸入無效,最好是寫一個小解析器和提供反饋來代替。可以將用戶指向導致問題的角色,並提供更有用的和有針對性的錯誤消息。

在解析器中,您可以使用正則表達式來聲明字符串中的某些屬性以生成目標錯誤消息。例如,如果輸入必須包含6個字符,並且前3個字符是數字,而最後3個字母是字母字符,則可以編寫正則表達式來聲明輸入的長度以向用戶報告錯誤。

要麼是這樣,要麼只是使用正則表達式,並提供一個通用的錯誤消息(有關如何正確輸入的有用指導)。普通用戶應該能夠在最多2-3次嘗試中正確輸入數據。在此之上,它可能是惡意用戶,或者輸入的數據不適用於所有用戶,或者您的指令缺乏。