簡體   English   中英

與文章參考上的正則表達式匹配的模式

[英]Pattern matching with regex on article reference

我需要在PHP中模式匹配給定字符串中的許多文章引用,然后我想要提取它們。 引用最多可包含16位數字,每個數字可以具有不同的值。 有一點要知道:從數字11開始(包括數字11),輸入數據中的所有內容都是可選的(但是如果你在可選數字之后有一些有效的東西,那么這個數字必然是“ - ”)。 此外,如果直到結尾都有“ - ”,則可以截斷引用。 例如 :

A2 - L3500XM -----可以是A2 - L3500XM

D4 - L4652Z-4 ----可以是D4 - L4652Z-4

A3 - L5020MW4 --- A保持A3 - L5020MW4 --- A.

這些都是有效的參考。 這是我到目前為止所做的工作:

[DA][1-5][V\-][AN\-][LMFGHN][\d]{4}[H-RT-ZBD]([H-RT-ZBD\-]?)(?(-1)[1-4\-]?)

我達到了第11位,但這就是它變得棘手的地方。 這是我的示例參考:

 D1--L6000T-4 VALID D1--L6000T VALID D1--L6000T4----- INVALID D1--L6000T----- VALID 

我用VALID注釋了應該匹配的那些。 我的問題是我的正則表達式采用了所有這些(按預期截斷“ - ”),但第三個應該匹配,因為4對第11位無效。 我認為它確實采用4的原因是因為第10位是可選的,這意味着如果它不在那里我猜-1可能是指[H-RT-ZBD] ,它包含幾乎相同的字符? 所以我在這里有點迷失,我的問題是:我怎樣才能做到這一點? 有更容易的方法嗎 ? 甚至可以做到嗎?

模式規則:

digit number : pattern
1 :   [DA]
2 :   [1-5]
3 :   [V-]
4 :   [AN-]
5 :   [LMFGHN]
6-9 : \d{4}
10 :  [H-RT-ZBD]
11 :  [H-RT-ZBD-]?
12 :  [1-4-]?
13 :  [KRX-]?
14 :  [CPW-]?
15 :  [MT-]?
16 :  [A-C-]?

通常,要匹配的輸入字符串是具有大量空格和可能的任何字符的普通表。

以下正則表達式對您提供的所有規則和輸入的評估結果為true。 您可以復制整個塊並使用它,包括注釋。

$string = "D1--L6000T4------ A3--L5020MW4---A D4--L4652Z-4---- D1--L6000T";

preg_match_all(
    '/(                  # Matching the start of the group
       [DA]              # Digit 1
       [1-5]             # Digit 2
       [V-]              # Digit 3
       [AN-]             # Digit 4
       [LMFGHN]          # Digit 5
       \d{4}             # Digit 6-9
       [H-RT-ZBD]        # Digit 10
    (?:[H-RT-ZBD-]       # Digit 11
    (?:[1-4-]            # Digit 12
    (?:[KRX-]            # Digit 13
    (?:[CPW-]            # Digit 14
    (?:[MT-]             # Digit 15
       [A-C-]            # Digit 16
    ?)?)?)?)?)?)         # Closing all the groups and alternations
    (?:(?=(\s|%20))|$    # Matching a space (even %20) or end of string. This is done to exclude partial matches.
    )/x', 
    $string, $matches
);

var_dump($matches);

關於我改變了什么的幾點說明。

刪除了字符組內的短划線的轉義。 如果它被放置在不標記間隔的地方,它將像任何其他角色一樣。

刪除了\\d周圍的字符組[ ]

我沒有將第11個數字作為可選項,而是寫出模式與11和out的不同之處。 組的遞歸可選性確保如果第12個字符能夠匹配,則需要第11個字符,依此類推。

結束邊界

我已經將(?:(?=(\\s|%20))|$到正則表達式的末尾,這樣可以確保只有在沒有后續字符的情況下才會匹配此模式。這樣做是折扣部分匹配的唯一方法,例如D1--L6000T中的D1--L6000T4------當你不能保證每個模式都用空格分隔時。坦率地說我覺得很奇怪。

檢索比賽

構造正則表達式使得完整模式可用作匹配部分,或匹配數組中的索引0。

我猜-1可以引用[H-RT-ZBD] ,它包含幾乎相同的字符?

不,它確實是指([H-RT-ZBD\\-]?) ,這是最后一個捕獲組。 然而,它始終匹配,因為字母是可選的 - 然后捕獲空字符串。 你的條件是真的。

我猜你應該選擇你的角色捕捉組,而不是捕捉一個可選角色(參見http://www.regular-expressions.info/captureall.html的差異)。 所以試試吧

[DA][1-5][V-][AN-][LMFGHN]\d{4}[H-RT-ZBD]([H-RT-ZBD-])?(?(-1)([1-4-]))?(?(-1)([KRX-]))?(?(-1)([CPW-]))?(?(-1)([MT-]))?(?(-1)[A-C-])?

如果您不需要捕獲組,則可以使用更自然的嵌套而不是條件來簡化表達式:

[DA][1-5][V-][AN-][LMFGHN]\d{4}[H-RT-ZBD](?:[H-RT-ZBD-](?:[1-4-](?:[KRX-](?:[CPW-](?:[MT-][A-C-]?)?)?)?)?)?

當然,你必須在任何情況下錨定你的表達式,以便與無效輸入的有效子部分匹配:-)你可以將它包裝在^ + $(?<!\\S) + (?!\\S)(?<=\\s|^) + (?=\\s|$)

您應該僅使用正則表達式來選擇可能的模式,以便從原始字符串中提取它們。

獲得所選潛在模式的數組后,使用IFSWITCH語句以及substr和其他字符串比較函數來確定每個模式是否有效。

否則,您可能會編寫過於復雜的正則表達式,這些正則表達式需要花費很長時間才能進行調試,而且更新時間太長而且沒有人會想要在之后使

暫無
暫無

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

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