正規表示式教程之位置匹配詳解

技術之光發表於2022-03-15

本文例項講述了正規表示式教程之位置匹配。分享給大家供大家參考,具體如下:

注:在所有例子中正規表示式匹配結果包含在源文字中的 之間,有的例子會使用Java來實現,如果是java本身正規表示式的用法,會在相應的地方說明。所有java例子都在JDK1.6.0_13下測試通過。

一、問題引入

如果想匹配一段文字中的某個單詞(暫不考慮多行模式,將在後面介紹),我們可能會像下面這樣:

文字: Yesterday is history, tomorrow is a mystery, but today is a gift.

正規表示式: is

結果: Yesterday  【is】 h 【is】tory, tomorrow  【is】 a mystery, but today  【is】 a gift.

分析:本來只是要匹配單詞is,但把其他單詞中包含的is也匹配出來了。要解決這個問題,使用邊界界定符,也就是在正規表示式裡用一些元字元來表明我們想讓匹配操作在什麼位置(或邊界)發生。

二、單詞邊界

一種常用的邊界是由限定符\b指定的單詞邊界,\b用來匹配單詞的開始和結尾。更確切地說,它是匹配這樣一個位置,這個位置位於一個能夠用來構成單詞的字元(字母、數字、下劃線,也就是與\w相匹配的字元)和一個不能用來構成單詞的字元(與\W相匹配的字元)之間。來看前面的例子:

文字: Yesterday is history, tomorrow is a mystery, but today is a gift.

正規表示式: \bis\b

結果: Yesterday  【is】 history, tomorrow  【is】 a mystery, but today  【is】 a gift.

分析:在原始文字中,單詞is的前後都有一個空格,而這與模式\bis\b匹配(空格是用來分隔單詞的字元之一)。而單詞history中也包含了is,因為它的前後分別有一個字元h和t,這兩個字元都不能與\b匹配。

如果不匹配一個單詞邊界,則使用\B。如:

文字: Please enter the nine-digit id as it appears on your color - coded pass-key.

正規表示式: \B-\B

結果: Please enter the  【nine-digit】 id as it appears on your color - coded  【pass-key】.

分析:\B-\B將匹配一個前後都不是單詞邊界的連字元,nine-digit和pass-key中連字元前後都沒有空格,所以能夠匹配,而color - coded中連字元前後都有空格,所以不能匹配。

三、字串邊界

單詞邊界可以用來進行與單詞有關的位置匹配(單詞開頭、結束、整個單詞等等)。而字串邊界也有著類似的用途,只不過是用來進行與字串有關的位置匹配(字串開頭、結束、整個字串等等)。用來定義字串邊界的元字元有兩個:一個是用來定義字串開頭的^,另一個是用來定義字串結尾的$。

比如要檢查一個XML文件的合法性,合法的XML文件都以<?xml…..?>這樣形式開頭:

文字:

<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="ear">
</project>

正規表示式: ^\s*<\?xml.*?\?>

結果:

<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="ear">
</project>

分析:^匹配一個字串的開頭位置,所以^\s*將匹配一個字串的開頭位置和隨後的零個或多個空白字元,因為<?xml>標籤前面允許有空格、製表符、換行符等空白字元

$元字元符的用法除了位置上的差異外,與^用法完全一樣。比如,檢查一個html頁面是否以</html>結尾,可以用模式:</[Hh][Tt][Mm][Ll]>\s*$

四、多行匹配模式

正規表示式可以通過一些特殊的元字元來改變另外一些元字元的行為。可以通過(?m) 來啟用多行匹配模式。多行匹配模式將使得正規表示式引擎把行分隔符當做一個字串分隔符來對待。在多行匹配模式下,^不僅匹配正常的字串開頭,還將匹配行分隔符(換行符)後面的開始位置,$不僅匹配正常的字串結尾,還將匹配行分隔符(換行符)後面的結束位置。

在使用時,(?m)必須出現在整個模式的最前面。比如,通過正規表示式把一段java程式碼中的單行註釋(以//開始)內容全部找出來。

文字:

publicDownloadingDialog(Frame parent){
     //Callsuper constructor, specifying that dialog box is modal.
     super(parent,true);
     //Setdialog box title.
     setTitle("E-mailClient");
     //Instructwindow not to close when the "X" is clicked.
     setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
     //Puta message with a nice border in this dialog box.
     JPanelcontentPanel = new JPanel();
     contentPanel.setBorder(BorderFactory.createEmptyBorder(5,5, 5, 5));
     contentPanel.add(newJLabel("Downloading messages..."));
     setContentPane(contentPanel);
     //Sizedialog box to components.
     pack();
     //Centerdialog box over application.
     setLocationRelativeTo(parent);
}

正規表示式: (?m)^\s*//.*$

結果:

         publicDownloadingDialog(Frame parent){
【              //Call superconstructor, specifying that dialog box is modal.】
                   super(parent,true);
【              //Set dialog boxtitle.】
                   setTitle("E-mailClient");
【              //Instruct windownot to close when the "X" is clicked.】
                   setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
【              //Put a messagewith a nice border in this dialog box.】
                   JPanelcontentPanel = new JPanel();
                   contentPanel.setBorder(BorderFactory.createEmptyBorder(5,5, 5, 5));
                   contentPanel.add(newJLabel("Downloading messages..."));
                   setContentPane(contentPanel);
【              //Size dialog boxto components.】
                   pack();
【              //Center dialogbox over application.】
                   setLocationRelativeTo(parent);
         }

分析:^\s*//.*$將匹配一個字串的開始,然後是任意多個空白字元,再後面是//,再往後是任意文字,最後是一個字串的結束。不過這個模式只能找出第一條註釋,加上(?m)字首後,將把換行符視為一個字串分隔符,這樣就可以把每一行註釋匹配出來了。

java程式碼實現如下(文字儲存在text.txt檔案中):

正規表示式:(?m)^\s*//.*$
結果:
         publicDownloadingDialog(Frame parent){
【              //Call superconstructor, specifying that dialog box is modal.】
                   super(parent,true);
【              //Set dialog boxtitle.】
                   setTitle("E-mailClient");
【              //Instruct windownot to close when the "X" is clicked.】
                   setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
【              //Put a messagewith a nice border in this dialog box.】
                   JPanelcontentPanel = new JPanel();
                   contentPanel.setBorder(BorderFactory.createEmptyBorder(5,5, 5, 5));
                   contentPanel.add(newJLabel("Downloading messages..."));
                   setContentPane(contentPanel);
【              //Size dialog boxto components.】
                   pack();
【              //Center dialogbox over application.】
                   setLocationRelativeTo(parent);
         }
分析:^\s*//.*$將匹配一個字串的開始,然後是任意多個空白字元,再後面是//,再往後是任意文字,最後是一個字串的結束。不過這個模式只能找出第一條註釋,加上(?m)字首後,將把換行符視為一個字串分隔符,這樣就可以把每一行註釋匹配出來了。
java程式碼實現如下(文字儲存在text.txt檔案中):

輸出結果如下:

//Call super constructor, specifying that dialog box is modal.
//Set dialog box title.
//Instruct window not to close when the "X" is clicked.
//Put a message with a nice border in this dialog box.
//Size dialog box to components.
//Center dialog box over application.

五、小結

正規表示式不僅可以用來匹配任意長度的文字塊,還可以用來匹配出現在字串中特定位置的文字。\b用來指定一個單詞邊界(\B剛好相反)。^和$用來指定單詞邊界。如果與(?m)配合使用,^和$還將匹配在一個換行符處開頭或結尾的字串。在接下來的文章中將介紹子表示式的使用。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70015103/viewspace-2871089/,如需轉載,請註明出處,否則將追究法律責任。

相關文章