使用Regex處理字串中多個子串

來源:互聯網
上載者:User

起因

昨天工作時遇到這樣一種需求:將檢索出來的字串中的關鍵字標記成紅色,關鍵字的個數是不定的。猛一看其實挺簡單的,但我一時卻沒有想到太好的辦法,因為並不是簡單地將目標字串替換成統一的字串,而是對目標字串進行一定的處理;而且說實話,在Java中用Regex的時候還真不多,所以對Regex一直是似懂非懂,但我相信正則肯定能解決,而且應該很簡單。

帶著這樣一種信心查閱了一下JDK的API,覺得還真是挺簡單,至少不止一種解決方式。

Java中的實現

其實問題就在於我們如何擷取正則匹配到的字串,然後做一下處理再拼接回原串就可以了。比如我們拿到了匹配字串subStr,將其用span標籤包起來:

"<span style='color: red;'>" + subStr + "</span>"

那麼我們如何獲得Regex匹配到的字串呢?這應該和我們編寫的Regex相關,因為關鍵字的個數是不定的,那麼我們可以將每一個關鍵字作為運算式對原字串作相應處理,當一個關鍵字匹配處理結束後再進行下一個關鍵字的操作,直至結束:

public String signKeywordToRed (String content, String [] keywords) {StringBuffer stringBuffer = new StringBuffer();for(String keyword : keywords) {if (!StringUtils.isEmpty(keyword)) {Matcher matcher = Pattern.compile(keyword, Pattern.CASE_INSENSITIVE).matcher(content);while(matcher.find()) {matcher.appendReplacement(stringBuffer, "<span style='color: red;'>" + matcher.group(0) + "</span>");}matcher.appendTail(stringBuffer);}content = stringBuffer.toString();stringBuffer.delete(0, stringBuffer.length());}return content;}

因為在Regex分組中,組0始終代表的是整個運算式,所以我們可以用group(0)取得正則(即關鍵字)匹配到的字串;除了group(0)方式取得匹配字串外,還可以用截取字串的方式來取得匹配字串,比如可以這樣做:

matcher.appendReplacement(resultBuffer, "<span style='color: red;'>" + content.substring(matcher.start(), matcher.end()) + "</span>");

其中Matcher對象的start()方法和end()方法分別返回匹配字串的開始索引和結束索引;另外Pattern.compile()方法中的第二個參數Pattern.CASE_INSENSITIVE表示不區分大小寫。

除了上述方法,我們應該還能想到另外一種方式:即將所有的關鍵字組合成一個Regex,只編譯一次運算式即可。比如我們有兩個關鍵字man和love,我們的正則可以這樣寫:(man|love),那麼在關鍵字個數不定的情況 下我們就可以這樣做:

public String signKeywordToRed(String content, String [] keywords) {StringBuffer regExp = new StringBuffer("("); for(String keyword : keywords) {regExp.append(keyword).append("|");}regExp.deleteCharAt(regExp.length() - 1).append(")");Matcher matcher = Pattern.compile(regExp.toString(), Pattern.CASE_INSENSITIVE).matcher(content);StringBuffer resultBuffer = new StringBuffer();while(matcher.find()) {matcher.appendReplacement(resultBuffer, "<span style='color: red;'>" + matcher.group(1) + "</span>");}matcher.appendTail(resultBuffer);return resultBuffer.toString();}

在這個例子中,其實上面的group(1)換成group(0)也是可以的。

Javascript中的實現

將需求實現之後,突然想到這種問題放在JS中應該更簡單,因為Javascript靈活性是Java這種比較嚴謹的語言難以企及的。於是著手試了一下,果然很簡單,僅需幾行代碼就可以了,如下所示:

function signKeywordToRed(content, keywords) {var regExp = new RegExp("(" + keywords.join("|") + ")", 'gi');return content.replace(regExp, "<span style='color: red;'>$1</span>");}

在這裡$1與Java中的group(1)原理是一樣的,都是Regex第一個分組所匹配到的字串。需要注意的是這裡假定傳進方法的參數keywords是數組,這裡只是個小例子,如果需要處理更嚴謹的話,需要判斷一下是否為數組。

下面貼個小例子:

<html><head><script type="text/javascript">function fun() {var kw = prompt('請輸入要標記為紅色的詞語, 多個詞語之間用逗號分隔.');var target = document.getElementById('info');target.innerHTML = signKeywordToRed(target.innerText, kw.split(','));}function signKeywordToRed(content, keywords) {var regExp = new RegExp("(" + keywords.join("|") + ")", 'gi');return content.replace(regExp, "<span style='color: red;'>$1</span>");}</script></head><body><button onclick="fun()">Click Me</button><span id="info">i'm alove higher man.loveseaManrch bugmAn</span></body></html>

Javascript中String對象的replace()方法是個很強大的方法,需要好好研究一番。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.