快速入門
教學
工具和語言
範例
參考
書籍評論
正規表示式工具
grep
PowerGREP
RegexBuddy
RegexMagic
一般應用程式
EditPad Lite
EditPad Pro
語言和函式庫
Boost
Delphi
GNU (Linux)
Groovy
Java
JavaScript
.NET
PCRE (C/C++)
PCRE2 (C/C++)
Perl
PHP
POSIX
PowerShell
Python
R
Ruby
std::regex
Tcl
VBScript
Visual Basic 6
wxWidgets
XML Schema
Xojo
XQuery 和 XPath
XRegExp
資料庫
MySQL
Oracle
PostgreSQL
本網站上的更多資訊
簡介
正規表示式快速入門
正規表示式教學
替換字串教學
應用程式和語言
正規表示式範例
正規表示式參考
替換字串參考
書籍評論
可列印 PDF
關於本網站
RSS Feed 和部落格
RegexBuddy—The best regex editor and tester for Tcl developers!

Tcl 有三種正規表示式風格

Tcl 8.2 和更新版本支援三種正規表示式風格。Tcl 手冊頁將它們稱為基本正規表示式 (BRE)、延伸正規表示式 (ERE) 和進階正規表示式 (ARE)。BRE 和 ERE 主要用於與 Tcl 舊版本保持向後相容性。這些風格實作 POSIX 標準 中定義的兩種風格。ARE 是 Tcl 8.2 中的新功能。它們是預設且建議使用的風格。此風格實作 POSIX ERE 風格,並加入許多額外功能。這些功能大多是受到 Perl 正規表示式 中類似功能的啟發。

Tcl 的正規表示法支援是基於 Henry Spencer 為 Tcl 開發的函式庫。此函式庫自此已用於許多其他程式語言和應用程式,例如 PostgreSQL 資料庫wxWidgets GUI 函式庫 for C++。本 正規表示法教學 中所有關於 Tcl 的內容都適用於任何使用 Henry Spencer 的進階正規表示法的工具。

Tcl 進階正規表示法和 Perl 風格正規表示法之間有許多重要的差異。Tcl 使用 \m\M\y\Y 表示 字詞界線。Perl 和大多數其他現代正規表示法風格使用 \b\B。在 Tcl 中,後兩個分別匹配退格鍵和反斜線。

Tcl 也採用完全不同的方式來處理 模式修改器(?letters) 語法相同,但可用的模式字母及其含義卻大不相同。您不必將模式修改器新增到正規表示法中,而是可以將更具描述性的開關(例如 -nocase)傳遞給 regexpregsub 命令以供某些模式使用。不支援 (?modes:regex) 風格的模式修改器跨度。模式修改器必須出現在正規表示法的開頭。它們會影響整個正規表示法。正規表示法中的模式修改器會覆寫命令開關。Tcl 支援這些模式

如果您在 Tcl 和其他程式語言中使用正規表示式,請在處理與換行相關的比對模式時小心。Tcl 的設計者發現 Perl 的 /m/s 模式令人困惑。它們確實令人困惑,但至少 Perl 只有兩個,而且它們只影響一件事。在 Perl 中,/m(?m) 啟用「多行模式」,這會讓 插入符號和美元符號 在換行符號之後和之前比對。預設情況下,它們只會在字串的最開始和最後比對。在 Perl 中,/s(?s) 啟用「單行模式」。此模式會讓 比對所有字元,包括換行符號。預設情況下,它不會比對換行符號。Perl 沒有模式修改器可以將換行符號排除在 取反字元類別 之外。在 Perl 中,[^a] 比對除了 a 之外的任何東西,包括換行符號。排除換行符號的唯一方法是寫成 [^a\n]。Perl 的預設比對模式就像 Tcl 的 (?p),除了取反字元類別的差異之外。

為什麼要將 Tcl 與 Perl 進行比較?許多流行的正規表示式風格,例如 .NETJavaPCREPython,都支援相同的 (?m)(?s) 修改器,其預設值和效果與 Perl 中完全相同。取反字元類別在所有這些語言和函式庫中運作方式相同。很遺憾 Tcl 沒有遵循 Perl 的標準,因為 Tcl 的四個選項和 Perl 的兩個選項一樣令人困惑。它們加在一起成為一碗非常美味的字母湯。

如果您忽略 Tcl 的選項會影響取反字元類別的事實,您可以使用下表在 Tcl 的換行模式和 Perl 風格的換行模式之間進行轉換。請注意,預設值不同。如果您不使用任何開關,(?s).. 在 Tcl 中是等效的,但在 Perl 中則不是。

TclPerl錨點
(?s)(預設)(?s)僅限字串開頭和結尾任何字元
(?p)(預設)僅限字串開頭和結尾任何字元,但排除換行符
(?w)(?sm)字串開頭和結尾,以及換行符任何字元
(?n)(?m)字串開頭和結尾,以及換行符任何字元,但排除換行符

正規表示式作為 Tcl 字詞

你可以使用雙引號(例如 "my regexp")或大括號(例如 {my regexp})將正規表示式插入 Tcl 原始碼中。由於大括號不會像引號那樣進行任何替換,因此它們是正規表示式的最佳選擇。

你唯一需要擔心的是,正規表示式中未跳脫的大括號必須平衡。已跳脫的大括號不需要平衡,但用於跳脫大括號的反斜線仍是正規表示式的一部分。你可以透過跳脫正規表示式中的所有大括號(用作 量詞 的大括號除外)來輕鬆滿足這些需求。這樣一來,你的正規表示式將會按預期運作,而且你無需在將其貼入 Tcl 原始碼時進行任何變更,只要在正規表示式周圍加上一對大括號即可。

正規表示式 ^\{\d{3}\\$ 會比對一個完全由開大括號、三個數字和一個反斜線組成的字串。在 Tcl 中,這會變成 {^\{\d+{3}$\\}。只要你跳脫正規表示式中的字面大括號,就不需要加倍反斜線或進行任何類型的跳脫。{\{ 都是用於比對 Tcl ARE 中單一開大括號的有效正規表示式(以及任何 Perl 風格的正規表示式風味)。只有後者才能在用大括號括起來的 Tcl 字面值中正確運作。

尋找正規表示式比對

在 Tcl 中,你可以使用 regexp 指令來測試正規表示式是否比對(字串的)一部分,並擷取比對的部分。指令的語法如下:

regexp ?switches? regexp subject ?matchvar? ?group1var group2var ...?

regexp 命令之後,你可以放置上面清單中零個或多個開關,以指示 Tcl 應如何套用正規表示式。唯一需要的參數是正規表示式和主旨字串。你可以使用大括弧指定一個文字正規表示式,就像我剛剛解釋的那樣。或者,你可以參照任何包含從檔案或使用者輸入中讀取的正規表示式的字串變數。

如果你將變數名稱傳遞為附加參數,Tcl 會將與正規表示式相符的字串部分儲存在該變數中。如果比對嘗試失敗,Tcl 不會 將變數設定為空字串。如果正規表示式有擷取群組,你可以新增其他變數名稱來擷取與每個群組相符的文字。如果你指定的變數少於正規表示式中的擷取群組,則不會儲存與其他群組相符的文字。如果你指定的變數多於正規表示式中的擷取群組,則如果整體正規表示式比對成功,其他變數會設定為空字串。

如果可以比對(部分)字串,regexp 命令會傳回 1;如果沒有比對,則傳回 0。以下指令碼以不分大小寫的方式將正規表示式 my regex 套用至儲存在變數 subjectstring 中的字串,並顯示結果

if [
  regexp -nocase {my regex} $subjectstring matchresult
] then {
  puts $matchresult
} else {
  puts "my regex could not match the subject string"
}

regexp 命令支援另外三個不是正規表示式模式修改器的開關。-all 開關會導致命令傳回一個數字,表示正規表示式可以比對的次數。儲存正規表示式和群組比對的變數只會儲存字串中的最後一個比對。

-inline 開關會指示 regexp 命令傳回一個陣列,其中包含與正規表示式相符的子字串以及與所有擷取群組相符的所有子字串。如果你也指定了 -all 開關,陣列將包含第一個正規表示式比對、第一個比對的所有群組比對、然後是第二個正規表示式比對、第一個比對的群組比對,依此類推。

-start 這個開關後面必須接一個數字(作為一個獨立的 Tcl 字),表示 Tcl 應嘗試比對的主題字串中的字元偏移量。起始位置之前的任何內容都會對正規表示式引擎隱藏。這表示 \A 會在您使用 -start 指定的字元偏移量進行比對,即使該位置不在字串的開頭。

取代正規表示式比對結果

使用 regsub 指令,您可以在字串中取代正規表示式比對結果。

regsub ?開關? 正規表示式 主題 取代 ?結果變數?

就像 regexp 指令一樣,regsub 會接受零個或多個開關,後面接著一個正規表示式。它支援相同的開關,但 -inline 除外。如果您要取代字串中的所有比對結果,請記得指定 -all

正規表示式後的引數應該是取代文字。您可以使用大括號語法指定文字取代,或參照字串變數。regsub 指令會辨識取代文字中的幾個後設字元。您可以使用 \0 作為整個正規表示式比對結果的佔位符,並使用 \1\9 來表示由前九個 擷取群組 之一比對到的文字。您也可以使用 & 作為 \0 的同義詞。請注意,縮寫符號前面沒有反斜線。& 會以整個正規表示式比對結果取代,而 \& 會以文字縮寫符號取代。使用 \\ 來插入文字反斜線。您只需要在反斜線後接數字時才需要跳脫反斜線,以防止組合被視為反向參照。同樣地,為了避免不必要的反斜線重複,您應該使用大括號將取代文字括起來,而不是使用雙引號。使用大括號時,取代文字 \1 會變成 {\1},而使用引號時會變成 "\\1"

如果您將變數參考作為最後一個參數傳遞,該變數會接收套用替換後的字串,而 regsub 會傳回一個整數,表示已進行的替換次數。Tcl 8.4 及更新版本允許您省略最後一個參數。在這種情況下,regsub 會傳回套用替換後的字串。

| 快速開始 | 教學 | 工具和語言 | 範例 | 參考 | 書籍評論 |

| grep | PowerGREP | RegexBuddy | RegexMagic |

| EditPad Lite | EditPad Pro |

| Boost | Delphi | GNU (Linux) | Groovy | Java | JavaScript | .NET | PCRE (C/C++) | PCRE2 (C/C++) | Perl | PHP | POSIX | PowerShell | Python | R | Ruby | std::regex | Tcl | VBScript | Visual Basic 6 | wxWidgets | XML Schema | Xojo | XQuery 和 XPath | XRegExp |

| MySQL | Oracle | PostgreSQL |