如何寫出一個符合要求的正則

2022-08-05 15:45:11 字數 3291 閱讀 5044

如果你正在苦惱如何寫一個正則的話,那麼或許本文對你有所幫助

文中的這個例子或許同個字串擷取同樣可以做到,但本文僅嘗試以純正則的角度解決問題

首先看一下這個例子

d             >> -    mj 1989

d - mj 2000>>

d - 17.05.2011>> - mj 2013

d - mj 2010>> - 01.11.2010

d - 24.06.2002>> - 25.08.2002

d - mj 2011>> - mj 2011

需求是獲取br標籤中的mj 2000或者25.08.2002這個字串;在>>這個左邊的是開始日期,右邊是結束日期,最後的結果需要給出開始年份和結束日期的字串,並且如果任意一個日期為空,也需要提取出來,因為需要提取出的一個是開始日期還是結束日期

在開始之前,我們假設一下我們最後可以的到的結果

分組1為開始年份 比如mj 2000或者為空串

分組2為開始年份 比如mj 2013或者為空串

好的 我們現在以這個結果去找尋可能的解決方案

首先我們可以觀察得到這樣的規律

這個字串以若干的

開頭和結尾,並且在開頭的

結束之後會有個d

那麼我們的開頭為^

(這個地方先假設只有一個

),前文說到會有多個

,所以我們需要用量詞來形容,並且我們需要形容的是整個

所以需要用括號包裹起來,我們假設至少會有一個

所以我們的式子變為^(

)+`接下來匹配開頭br 結束的d

式子為^(

)+`同理可得結尾式子應該是(

)+$然後我們先把首尾銜接起來,中間使用.*先匹配所有文字,同時使用分組包裹 即(.*)

^(

)+d(.*)(

)+$可以得到這樣的匹配結果

我們會發現實際上我們只是為了

這個標籤用量詞進行形容,我們並不關心他裡面是什麼值將需要從不分組上獲取到的,但是現在我們

現在可以從看到實際上我們將這個標籤的值獲取到了分組,並且佔用了分組1的位置,導致我們的結果獲取到了不必要的文字(如果可以接受分組1 並不是我們需要的結果 也可以忽略)

所以我們使用非捕獲組(?:)來包裹一個式子 用來表示這個我們只是想對整體進行一些操作,但是我們並不關心這個式子是什麼內容

所以我們的式子變成^(?:

)+d(.*)(?:

)+$

我們也可以看到我們現在獲取到了整個除了br的文字內容

通過>>可以將文字內容分為開始時間和結束時間

所以分兩部分提取內容 式子為^(?:

)+d(.*)>>(.*)(?:

)+$

可以看到每個匹配的項中都有且只有兩個分組,並且分組中含有我們需要的日期

那麼我們接下來需要做的就是在這個文字中提起我們需要的部分

先看左邊

有三種情況空的 、mj 2000以及24.06.2002 三種情況 並且存在一些空格

所以我們用(mj \d) 和 (\d.\d.\d) 和 () 三個分組提取內容

即()|(mj \d)|(mj \d)|(\d.\d.\d)

因為可能在日期之前存在空格或者橫槓 所以我們用[- ]+來匹配

接下來我們用[- ]*(()|(mj \d)|(mj \d)|(\d\.\d\.\d))來替換第一個左邊的.*

得到^(?:

)+d([- ]*(()|(mj \d)|(\d\.\d\.\d)))>>(.*)(?:

)+$

發現實際上再一次因為組的關係我們捕獲了整串左邊的文字,所以我們再次使用非捕獲組來修復這個問題

^(?:

)+d(?:[- ]*(()|(mj \d)|(\d\.\d\.\d)))>>(.*)(?:

)+$

我們又發現實際上分組1和分組2是相同的內容

這個地方有兩種處理方式

第一種,將匹配每一種日期情況的分組去除或者改為非捕獲組

^(?:

)+d(?:[- ]*(|mj \d|\d\.\d\.\d))>>(.*)(?:

)+$^(?:

)+d(?:[- ]*((?:)|(?:mj \d)|(?:\d\.\d\.\d)))>>(.*)(?:

)+$第二種,將包裹所有日期可能的分組改為非捕獲組(這個地方可以思考測試一下為什麼不能把這個分組去除

無論哪種情況 都可以得到這個結果

同理將左邊的表達替換到右邊 就可以得到最後的結果

^(?:

)+d(?:[- ]*(|mj \d|\d\.\d\.\d))>>(?:[- ]*(|mj \d|\d\.\d\.\d))(?:

)+$

即分組1 是開始日期 分組2是結束日期

使用到的工具**