1. 程式人生 > >正則表示式(Regular Expression)教程

正則表示式(Regular Expression)教程

正則表示式簡介

  • 為什麼需要正則表示式
    • 文字的複雜處理
  • 正則表示式的優勢和用途
    • 一種強大而靈活的文字處理工具;
    • 大部分程式語言、資料庫、文字編輯器、開發環境都支援正則表示式
  • 正則表示式定義:
    • 正如它的名字一樣是描述了一個規則,通過這個規則可以匹配一類字串。
    • 學習正則表示式很大程度上就是學習正則表示式的語法規則
  • 開發中使用正則表示式的流程:
    • 分析所要匹配的資料,寫出測試用的典型資料
    • 在工具軟體中進行匹配測試
    • 在程式中呼叫通過測試的正則表示式

正則表示式語法

普通字元

  • 字母、數字、漢字、下劃線、以及沒有特殊定義的標點符號,都是“普通字元”。表示式中的普通字元,在匹配一個字串的時候,匹配與之相同的一個字元。

簡單的轉義字元

轉義字元 含義
\n 換行符
\t 製表符
\\ 代表\本身
\^,\$,\.,\(,\),\{,\},\?,\+,\*,|,\[,\] 匹配這些字元本身

標準字元集合

  • 能夠與“多種字元”匹配的表示式
  • 注意區分大小寫,大寫是相反的意思
符號 含義
\d 任意一個數字,0~9中任意的一個
\w 任意一個字母或數字或下劃線,依舊是A~Z,a~z,0~9, _中任意一個
\s 包括空格、製表符、換行符和空白字元的其中任何一個
. 小數點可以匹配除了”\n”以外的任意一個字元,如果要匹配包括”\n”在內的所有字元,一般用[\s\S]

自定義字元集合:

  • [] 方括號匹配方式,能夠匹配方括號中任意一個字元
表示式 含義
[[email protected]] 匹配”a”或”b”或”4”或”@”
[^abc] 匹配”a”,”b”,”c”之外的任意一個字元
[f-k] 匹配”f”~”k”之間的任意一個字母
[^A-F0-3] 匹配”A”~”F”,”0”~”3”之外的任意一個字元

- 正則表示式的特殊符號,被包含到中括號中,則失去了特殊意義,除了^,- 之外
- 標準字元集合,除了小數點外,如果被包含於中括號,自定義字元集合將包含該集合。比如:[\d.-+]將匹配:數字、小數點、+、-

量詞(Quantifier)

  • 修飾匹配次數的特殊符號
表示式 含義
{n} 表示式重複n次
{m,n} 表示式至少重複m次,最多重複n次
{m,} 表示式至少重複m次
? 匹配表示式0次或者1次,相當於{0,1}
+ 表示式至少出現1次,相當於{1,}
* 表示式不出現或者出現任意次,相當於{0,}

- 匹配次數中的貪婪模式(匹配的字元越多越好,預設!)
- 匹配次數中的非貪婪模式(匹配的字元越少越好,修飾匹配次數的特殊符號後再加上一個?

字元邊界

  • (本組標記匹配的不是字元而是位置,符合某種條件的位置)
符號 含義
^ 與字串開始的地方匹配
$ 與字串結束的地方匹配
\b 匹配一個單詞邊界

- \b 匹配這樣一個位置:前面的字元和後面的字元不全是\w

選擇符和分組

表示式 作用
| 分支結構 左右兩邊表示式之間“或”關係,匹配左邊或者右邊
() 捕獲組 (1)在被修飾匹配次數的時候,括號中的表示式可以作為整體被修飾.(2)取匹配結果的時候,括號中的表示式匹配到的內容可以背單獨的到(3)每一對括號會分配一個編號,使用()的捕獲根據左括號的順序從1開始自動編號。捕獲元素編號為零的第一個捕獲使由整個正則表示式模式匹配的文字
?:Expression 非捕獲組 一些表示式中,不得不使用(),但又不需要儲存()中的表示式匹配的內容,這是可以使用非捕獲組來抵消使用()帶來的副作用

- 反向引用(\nnn)每一對() 都會分配一個編號,使用() 的捕獲根據左括號的順序從1開始自動編號。通過反向引用,可以對分組已捕獲的字串進行引用。

預搜尋(零寬斷言)

  • 只進行子表示式的匹配,匹配內容不計入最終的匹配結果,是零寬度
  • 這個位置應該符合某個條件。判斷當前位置的前後字元,是否符合制定的條件,但不匹配前後的字元。是對位置的匹配
  • 正則表示式匹配過程中,如果子表示式匹配到的是字元內容,而非位置,並被儲存到最終的匹配結果中,那麼就認為這個子表示式是佔有字元的;如果子表示式匹配到的僅僅是位置,活著匹配的內容並不儲存到最終的匹配結果中,那麼就認為這個子表示式是零寬度的。佔有字元還是零寬度,是針對匹配的內容是否儲存到最終的匹配結果中而言的。
表示式 含義
(?=exp) 斷言自身出現的位置的後面能夠匹配表示式exp
(?<=exp) 斷言自身出現的位置的前面能夠匹配表示式exp
(?!exp) 斷言此位置的後面不能匹配表示式exp
(?<!exp) 斷言次位置的前面不能匹配表示式exp

正則表示式的匹配模式

  • IGNORECASE忽略大小寫模式
    • 匹配時忽略大小寫
    • 預設情況下,正則表示式是要區分大小寫的
  • SINGLELINE 單行模式
    • 整個文字看作一個字串,只有一個開頭,一個結尾
    • 使小數點. 可以匹配包含換行符(\n)在內的任意字元。
  • MULTILINE 多行模式
    • 每行都是一個字串,都有開頭和結尾。
    • 在指定了MULTILINE之後,如果需要僅匹配字串開始和結束位置,可以使用\A\Z

常用正則表示式列表

含義 表示式
匹配中文字元 [\u4e00-\u9fa5]
匹配空白行 \n\s*\r
匹配HTML標記 <(\S*?)[^>]*>.*?</\1>|<.*?/>
匹配首尾空白字元 ^\s*|\s*$
匹配Email地址 \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配網址URL [a-zA-Z]+://[^\s]*
匹配國內電話號碼 \d{3}-\d{8}|\d{4}-\d{7}
匹配騰訊QQ號碼 [1-9][0-9]{4,}
匹配中國郵編 [1-9]\d{5}(?!\d)
匹配身份證號碼 \d{15}|\d{18}
匹配ip地址 \d+\.\d+\.\d+\.\d+

在編輯器中使用正則表示式查詢

  • 一般在各種IDE或文字編輯器都支援正則表示式的查詢(Ctrl+F或Cmd+F 調出查詢,勾選正則查詢)
  • Sublime Text
    這裡寫圖片描述
  • Intel IDEA
    這裡寫圖片描述

爬蟲原理程式碼

package com.coderbean.regex.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 網路爬蟲取連結小Demo
 *
 * Created by Chang on 15/10/7.
 */
public class WebSpiderTest {
    public static void main(String[] args) {
        String destStr = getURLContent("http://www.163.com","gbk");
//        System.out.println(destStr);
//        //取到的是超連結的整個內容
//        Pattern pattern = Pattern.compile("<a[\\s\\S]+?</a>");  
        String regexStr = "href=\"(http://.+?)\"";

        List<String> list = getMatherSubstrs(destStr,regexStr);
        for(String temp:list){
            System.out.println(temp);
        }

    }
    public static List<String> getMatherSubstrs(String destStr,String regexStr){

        List<String> list = new ArrayList<String>();
        Pattern pattern = Pattern.compile(regexStr);
        Matcher matcher = pattern.matcher(destStr);

        while(matcher.find()){
            list.add(matcher.group(1));
        }
        return list;
    }
    /**
     * 獲得URL對應的網頁的內容
     * @param urlStr
     * @return
     */
    public static String getURLContent(String urlStr, String charset){
        try {
            URL url = new URL(urlStr);
            StringBuilder sb = new StringBuilder();
            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(url.openStream(), Charset.forName(charset)));
            String temp = "";
            while(null!=(temp = bufferedReader.readLine())) {
                sb.append(temp);
                sb.append('\n');
            }
            return sb.toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}