[查漏補缺]正則表達式匹配算法

The fool doth think he is wise, but the wise man knows himself to be a fool. 
愚者總自覺得聰明,智者則有自知之明。

引言

智者千慮,必有一失;愚者千慮,必有一得。在不少文本編輯器裏,正則表達式一般被用來檢索、替換那些匹配某個模式的文本。正則表達式也是先後端通吃,百無禁忌。git

正則表達式中,最重要的就是通配符。用到的思想仍是回溯算法。github

在這裏作了一個簡易版的正則表達式實現。只包含兩種通配符:正則表達式

  • * 匹配任意多個(大於等於 0 個)任意字符
  • ?匹配零個或者一個任意字符

全部源碼均已上傳至github:連接算法

實現

分析

  1. 依次考察正則表達式中的每一個字符,當是非通配符時,就直接跟文本的字符進行匹配,若是相同,則繼續往下處理;若是不一樣,則回溯。
  2. 若是遇到特殊字符的時候,根據通配符來處理不一樣的匹配方案。若是匹配到沒法匹配的時候,則進行回溯,從新選擇一種匹配方案,而後再繼續匹配剩下的字符。

初始化

/**
     * 標識
     */
    private boolean match;
    /**
     * 正則表達式
     */
    private char[] patChars;
    /**
     * 長度
     */
    private int plen;

    /**
     * 初始化
     *
     * @param patten 正則表達式
     */
    private Pattern(String patten) {
        patChars = patten.toCharArray();
        this.plen = patChars.length;
        match = false;
    }複製代碼

匹配

private boolean isMatch(String txt) {
        match = false;
        char[] txtChars = txt.toCharArray();
        int tlen = txtChars.length;
        recursiveMatch(0, 0, txtChars, tlen);
        return match;
    }複製代碼

回溯算法

這裏其實就是一個大型的if-else,判斷符合哪種狀況,而後進行遞歸。若是再加幾種狀況,也就是多加一個if-else,這樣的話if-else嵌套層級太多,能夠考慮使用switch或者使用設計模式,這是後話,暫且不提。後端

private void recursiveMatch(int ti, int pj, char[] txtChars, int tlen) {
        if (match) return;
        if (pj == plen) {
            if (ti == tlen) match = true;
            return;
        }

        if (patChars[pj] == '*') {//* 任意字符
            for (int i = 0; i < tlen - ti; i++) {
                recursiveMatch(ti + i, pj + 1, txtChars, tlen);
            }
        } else if (patChars[pj] == '?') {//? 0 or 1
            recursiveMatch(ti, pj + 1, txtChars, tlen);
            recursiveMatch(ti + 1, pj + 1, txtChars, tlen);
        } else if (ti < tlen && patChars[pj] == txtChars[ti]) {
            recursiveMatch(ti + 1, pj + 1, txtChars, tlen);
        }
    }複製代碼

測試代碼

public static void main(String[] args) {
        String patten = "*@c?.com";
        Pattern pattern = new Pattern(patten);
        String txtT = "666@cc.com";
        boolean resT = pattern.isMatch(txtT);
        System.out.println(txtT + "的匹配結果:"  + resT);
        String txtF = "666@c.con";
        boolean resF = pattern.isMatch(txtF);
        System.out.println(txtF + "的匹配結果:"  + resF);
    }複製代碼

測試結果


經常使用的正則表達式

匹配網站設計模式

/((ht|f)tp(s)?:)?(\/\/*)?(w{3}.*)?[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g

其餘:傳送門bash

end


您的點贊和關注是對我最大的支持,謝謝!
相關文章
相關標籤/搜索