“And” 在正則表達式中 `&&`

嘗試使用正則表達式構建邏輯“與”運算時,我們有幾種方法可以遵循。 第一種方法似乎很明顯,但是如果考慮一下,默認情況下正則表達式是邏輯“和”的。 正則表達式中的每個順序字符都一起“與”。 如果您可以按順序表達您的陳述,那麼工作已經爲您完成。

但是,既然您已經搜索了這麼遠,我們可以假設您正在尋找更高級的東西。 爲方便起見,我們有兩個選擇:我們可以使用“ lookaheads”,或者如果您使用的任何工具或語言支持,也可以使用單獨的正則表達式執行第二次匹配。

先行查找實現邏輯“與”

先行查找和後向操作本質上是可以放在正則表達式上的額外約束。 您可以指定成功匹配需要滿足的其他模式。 以下是預讀表達式的示例。

(?=.*word1)(?=.*word2)(?=.*word3)

請注意,每個表達式都包含.* –這是因爲先行查找對位置敏感,並且從它們在模式中出現的位置開始匹配; 因此,例如,如果我們有一個類似於以下模式的模式:

^Start (?=.*kind)(?=.*good)(?=.*word).* deed$

此模式將匹配"Start with a good word and end with a kind deed" and “Start with a kind word and end with a good deed

總結:一旦開始第一個look-ahead,就保存表達式中的匹配位置。 第一個look-ahead中的.*匹配獲得kind之前需要的多個字符; 匹配位置被重置,並且下一個look-ahead向前搜索“good”; 最後但並非最不重要的一點是,我們最終的look-ahead將搜索“word”,然後像往常一樣恢復模式匹配。 匹配繼續使用表達式的基本.*,並繼續通過“deed”匹配到字符串的末尾。

這樣做的原因是,如上所述,因爲在評估每次環視後都會重置匹配位置。 這意味着我們相鄰的“and”look-ahea表達式的順序並不重要。 但是,如果我們將條件之一移至.*之後,則會看到不同的結果:

^Start (?=.*kind).*(?=.*good) deed.$

現在(?=.*good)排在我們的catch-all之後,我們之前的字符串都不匹配,因爲在評估.*之後不可能存在“good”。

提示,如果要匹配整個單詞而不是較長單詞的部分字符串,則需要在語句中添加單詞邊界:

^Start (?=.*\bkind\b)(?=.*\bgood\b)(?=.*\bword\b).* deed$

用您的語言實現邏輯“與”

如果所有其他方法都失敗了,那麼您應該始終簡單地執行另一場比賽,並使用所選編程語言的本機“and”邏輯功能將結果組合在一起,您總是會感到自在。 對於其他人來說,將來通常更容易維護,並且對中等數據集的性能影響很小。 例如,在Java中:

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class RegexTest
{
   @Test
   public void testRegex()
   {
      assertTrue(stringMatches("Start with a good word and end with a kind deed."));
      assertTrue(stringMatches("Start with a kind word and end with a good deed."));
      assertFalse(stringMatches("Start with a deed."));
   }

   private boolean stringMatches(String string)
   {
      return string.matches("^Start .* deed.$") && string.matches(".*good.*") && string.matches(".*kind.*");
   }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章