錙銖必較:程序員生存指南——正則表達式中使用斷言

想讓一個名詞聽起來特別高大上,最簡單的方法就是加很多修飾語。比如多源異構群智協(xié)同負反饋深度神經(jīng)網(wǎng)絡(當然了,這是我瞎編的)。在正則表達式中,有一種東西叫斷言,它的修飾語也很多:

  1. 零寬正向先行斷言
  2. 零寬負向先行斷言
  3. 零寬正向后行斷言
  4. 零寬負向后行斷言

斷言之所以叫“零寬”,是因為它們不會消費字符串,可以理解為斷言匹配的是位置。
斷言之所以叫“斷言”,是因為它們用來產(chǎn)生一個True\False的判定結果。
正向和負向分別指的是“應該出現(xiàn)”和“不應該出現(xiàn)”。
先行和后行分別指的是“此位置之后”和“此位置之前”。

這些東西有哪些實際的用途呢?Talk is cheap,show you the code!注意:以下例子是用scala寫的,這樣就避免了java字符串中“\”的轉義。


是時候展示真正的技術了

負向斷言例子1

假設有幾個文件全名:"file1.mp3","file2.bat","file3.txt",需要把英文句號之前的文件名提取出來。在這個過程中,需要忽略所有bat文件和mp3文件。

    val pattern ="""(\w+)\.(?!bat|mp3)(\w+)""".r
    val result = List("file1.mp3", "file2.bat", "file3.txt")
      .flatMap(s => {
        s match {
          case pattern(name, _) => List(name)
          case _ => Nil
        }
      })

這個負向先行斷言意思是此位置(句號后面)后面的字符串不能匹配“bat|mp3”,也就排除了bat和mp3擴展名。

負向斷言例子2

例如需要在標書中需要提取采購聯(lián)系人的姓名。

采購人:大連理工大學
聯(lián)系人:張三

這時采購聯(lián)系人可以認為是張三

采購人:大連理工大學
代理機構:大連理工代理公司
聯(lián)系人:李四

這時李四不能認為是采購聯(lián)系人,他應該是代理機構聯(lián)系人。(別問我為什么不用如日中天、如火如荼的自然語言處理,而非要用正則表達式作繭自縛)
這時的正則表達式為

(采購人)(?!.*代理機構).*?(聯(lián)系人:)(?<name>\S+)

它要求“采購人”后面出現(xiàn)“聯(lián)系人”,但是“采購人”后面不能有“代理機構”。

事實上,嚴格來說應該要求“采購人”和“聯(lián)系人”之間不能有“代理機構”,anyway......who cares?

正向斷言例子1

提取獲取標書的開始時間。

需要購買標書的投標人,請于3月15日到26日登錄某某網(wǎng)站
招標文件下載時間:北京時間3月15日至3月22日

這個正則表達式要求后面有日期,前面要出現(xiàn)“購買標書”、“招標文件下載”等關鍵詞,這些關鍵詞是特定名詞和特定動詞的組合。

(標書|招標文件|購買|下載).*(?<month>\d+)月(?<day>\d+)日

這個正則表達式問題在于名詞和動詞沒有要求同時出現(xiàn)。

((標書|招標文件) .*(購買|下載).*)|((購買|下載).*(標書|招標文件) .*)(?<month>\d+)月(?<day>\d+)日

這個要求倒是嚴格了,但是也太長了吧,增加了名詞和動詞時修改也不方便啊,要改兩個地方呢,容易出錯。

(?<=(標書|招標文件).*)(?<=(購買|下載).*)(\d+)月(\d+)日

這個正向斷言則解決了以上兩個問題。

正向斷言例子2

常見的密碼強度驗證一般都要求:

  1. 8-12位
  2. 必須有大寫字母
  3. 必須有小寫字母
  4. 必須有數(shù)字
^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{8,12}

這個正則表達式還是挺有用的,說不定哪次面試就用上了呢?。?!

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容