2011-03-19 35 views
1

我必須解析各種字符串並確定前綴,數字和後綴。問題是這些字符串可能有多種格式。對於如何解析它的最佳方式是找到字符串中最長的數字,然後將所有內容作爲前綴,並將其後的所有內容作爲後綴。是否有RegEx可以解析出字符串中最長的數字列表?

一些例子:

0001   - No prefix, Number = 0001, No suffix 
1-0001  - Prefix = 1-, Number = 0001, No suffix 
AAA001  - Prefix = AAA, Number = 001, No suffix 
AAA 001.01 - Prefix = AAA , Number = 001, Suffix = .01 
1_00001-01 - Prefix = 1_, Number = 00001, Suffix = -01 
123AAA 001_01 - Prefix = 123AAA , Number = 001, Suffix = _01 

的字符串可以拿出前綴和後綴的任何混合物,但關鍵的問題是數字部分始終是數字的最長的順序列表。

我試過了大多數但不是所有這些例子都適用的RegEx。我可能會錯過一些東西,或者RegEx在這種情況下不正確?

(正則表達式應該是.NET兼容)

UPDATE:對於那些有興趣,這裏是我想出了C#代碼:

var regex = new System.Text.RegularExpressions.Regex(@"(\d+)"); 
if (regex.IsMatch(m_Key)) { 
    string value = ""; 
    int length; 
    var matches = regex.Matches(m_Key); 
    foreach (var match in matches) { 
     if (match.Length >= length) { 
      value = match.Value; 
      length = match.Length; 
     } 
    } 
    var split = m_Key.Split(new String[] {value}, System.StringSplitOptions.RemoveEmptyEntries); 
    m_KeyCounter = value; 
    if (split.Length >= 1) m_KeyPrefix = split(0); 
    if (split.Length >= 2) m_KeySuffix = split(1); 
} 
+1

'123AAA 001_01 - Prefix = 123AAA,Number = 001,Suffix = _01' < - 這裏,前綴「123」中的數字與所討論的數字一樣長。沒辦法讓他們分開。 – polemon 2011-03-19 02:06:16

+0

好點。我將測試用例修改爲12AAA,因爲這樣的價值不太可能出現。如果是這樣,它將選擇最後一個最長的數字,而不是第一個最長的數字。 – 2011-03-19 02:40:14

回答

2

你說得對,這個問題不能純粹靠正則表達式解決。您可以使用正則表達式來「標記化」(詞法分析)輸入,但之後您需要進一步處理(解析)。因此,在這種情況下,我會使用(例如)簡單的正則表達式搜索(\d+)對輸入進行標記,然後處理令牌(解析)。這將涉及查看當前令牌是否比之前看到的令牌長。

爲了更好地理解正常表達式「解決」的問題類,並且在需要解析時,您可能需要查看一般編譯器理論,特別是在構造編譯器時使用正則表達式(例如http://en.wikipedia.org/wiki/Book:Compiler_construction)。

+0

(\ d +)搜索不會找到第一個數字序列嗎?你會如何找到所有可用的序列? – 2011-03-19 01:56:22

+0

如果您使用Regex.Matches,則不適用。它在輸入中返回一組匹配項。 – steinar 2011-03-19 02:00:35

+0

使用「(\ d +)」做RegEx.Split()似乎很好,因爲分解了字符串並允許我找到最長的數字。 – 2011-03-19 02:06:27

1

你輸入ISN經常這樣,一個正則表達式不會這樣做。我會通過(\ d +)遍歷所有數字組並找到最長的數字,然後以(.*)<number>(.*)的形式構建一個新的正則表達式來查找您的前綴/後綴。

或者,如果您對字符串操作感到滿意,您可能只需找到目標組的開始和結束並使用substr來查找pre/suf修復。

0

我不認爲你可以用一個正則表達式來做到這一點。我會找到字符串中的所有數字序列(可能帶有正則表達式),然後選擇最長的.NET代碼,並調用Split()

0

這完全取決於您的Regexp引擎。檢查您的Regexp環境以進行捕獲,其中可能存在類似於Perl中的自動變量的內容。

OK,讓我們來談談你的問題:

請記住,這兩個,NFA和DFA,幾乎每一個正則表達式引擎是貪婪的,這意味着,一個(\d+)總會找到最長的匹配,當它「絆倒」它。現在

,我可以從你的榜樣讓,是你總是需要一些中間部分,試試這個:

/^(.*\D)?(\d+)(\D.*)?$/ig 

的現在看變量$1$2$3。並非所有人都會存在:如果他們全部有三人,$2將持有您的電話號碼,其他變量,前綴部分。當其中一個前綴缺失時,將只設置變量$1$2,您必須親自看看,哪一個是整數。如果前綴和後綴都丟失,$1將保存該號碼。

這個想法是讓引擎對前幾個字符「絆倒」,並開始在中間匹配一個長號碼。

由於存在修飾符/g,因此您可以遍歷機器找到的所有可用組合,然後您可以簡單地選取一個您最喜歡的組合。

這個例子在PCRE中,但我相信.NET有一個兼容模式。

相關問題