1. 程式人生 > >tcl的正則表示式命令regexp的引數-lineanchor的理解

tcl的正則表示式命令regexp的引數-lineanchor的理解

tcl中正則表示式用得很多,往往一句程式碼能夠做好幾條其他語句才能做完的工作,高效快捷;

在處理string中逐行匹配的情況下往往是用引數-line,但其實-line相當於-lineanchor和-linestop。

在使用-lineanchor時的實踐:

Changes the behavior of “^” and “$” (the “anchors”) so they match the beginning and end of a line respectively. This is the same as specifying the (?w) embedded option (see the manual page). 

ex.

% set dataRtn {Select the version of EVDEV to use
> 1. Enable EVDEV 1.0.0.0 (EVDEV_1_0_0_0)
  2. Disable EVDEV (NO_EVDEV)
choice[1-2]:
*
* EVDEV Menu
*
Select the version of EVDEV_DEMO to use
> 1. Enable EVDEV_DEMO 1.0.0.0 (EVDEV_1_0_0_0_DEMO_1_0_0_0)
  2. Disable EVDEV_DEMO (NO_EVDEV_DEMO)
choice[1-2]:
Select the version of EVDEV_DRV to use
> 1. Enable EVDEV_DRV 1.0.0.0 (EVDEV_1_0_0_0_DRV_1_0_0_0)
  2. Disable EVDEV_DRV (NO_EVDEV_DRV)
choice[1-2]:

}

我想將上面變數dataRtn中的以*開頭的所有行刪除。

最開始認為引數-lineanchor會匹配到每行的開頭和結尾,不會存在貪婪匹配的問題:

regsub -all -lineanchor {^\*.*$} $dataRtn {} dataRtn1

% set dataRtn1
Select the version of EVDEV to use
> 1. Enable EVDEV 1.0.0.0 (EVDEV_1_0_0_0)
  2. Disable EVDEV (NO_EVDEV)
choice[1-2]:

%

發現錯了,雖然引數-lineanchor會讓^和$ 匹配行首和行尾,但是照樣是貪婪匹配。最後的$ 會一直匹配到整個string的結尾。

於是使用下面的命令:

% regsub -all -lineanchor {^\*.*?$} $dataRtn {} dataRtn1

% set dataRtn1
Select the version of EVDEV to use
> 1. Enable EVDEV 1.0.0.0 (EVDEV_1_0_0_0)
  2. Disable EVDEV (NO_EVDEV)
choice[1-2]:
                                                                           ---------------------------->這裡是空行
                                                                           ---------------------------->這裡是空行

                                                                           ---------------------------->這裡是空行
Select the version of EVDEV_DEMO to use
> 1. Enable EVDEV_DEMO 1.0.0.0 (EVDEV_1_0_0_0_DEMO_1_0_0_0)
  2. Disable EVDEV_DEMO (NO_EVDEV_DEMO)
choice[1-2]:
Select the version of EVDEV_DRV to use
> 1. Enable EVDEV_DRV 1.0.0.0 (EVDEV_1_0_0_0_DRV_1_0_0_0)
  2. Disable EVDEV_DRV (NO_EVDEV_DRV)
choice[1-2]:

期望把空行也刪除。

% regsub -all -lineanchor {^\*.*?\n$} $dataRtn {} dataRtn1

% set dataRtn1
Select the version of EVDEV to use
> 1. Enable EVDEV 1.0.0.0 (EVDEV_1_0_0_0)
  2. Disable EVDEV (NO_EVDEV)
choice[1-2]:

顯然不行,雖然$會匹配到行尾,但是似乎回車換行(\n)不是每行的結尾,所以匹配失敗,導致一直匹配到string的末尾;

% regsub -all -lineanchor {^\*.*?\n} $dataRtn {} dataRtn1

% set dataRtn1
Select the version of EVDEV to use
> 1. Enable EVDEV 1.0.0.0 (EVDEV_1_0_0_0)
  2. Disable EVDEV (NO_EVDEV)
choice[1-2]:
Select the version of EVDEV_DEMO to use
> 1. Enable EVDEV_DEMO 1.0.0.0 (EVDEV_1_0_0_0_DEMO_1_0_0_0)
  2. Disable EVDEV_DEMO (NO_EVDEV_DEMO)
choice[1-2]:
Select the version of EVDEV_DRV to use
> 1. Enable EVDEV_DRV 1.0.0.0 (EVDEV_1_0_0_0_DRV_1_0_0_0)
  2. Disable EVDEV_DRV (NO_EVDEV_DRV)
choice[1-2]:

這就是想要的結果了——不把\n當作結尾。