Tcl 有三种正则表达式风格Tcl 有三种正则表达式风格Tcl 有三种正则表达式风格Tcl 有三种正则表达式风格
  • 文章
  • 正则表达式
    • 工具
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容
发表 admin at 2024年3月5日
类别
  • 正则表达式
标签
Tcl 有三种正则表达式风格
  • 简
  • 繁
  • En
关于正则表达式 » 正则表达式工具和实用程序 » Tcl 有三种正则表达式风格

正则表达式工具
grep
语言和函数库
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
本网站上的更多信息
简介
正则表达式快速入门
正则表达式教程
替换字符串教程
应用程序和语言
正则表达式范例
正则表达式参考
替换字符串参考

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)传递给 regexp 和 regsub 命令以供某些模式使用。不支持 (?modes:regex) 风格的模式修改器跨度。模式修改器必须出现在正则表达式的开头。它们会影响整个正则表达式。正则表达式中的模式修改器会覆写命令开关。Tcl 支持这些模式

  • (?i) 或 -nocase 使正则表达式匹配大小写不敏感。
  • (?c) 使正则表达式匹配大小写敏感。此模式为默认值。
  • (?x) 或 -expanded 激活 自由间距正则表达式语法。
  • (?t) 禁用 自由间距正则表达式语法。此模式为默认值。“t”代表“紧密”,与“展开”相反。
  • (?b) 告诉 Tcl 将正则表达式的其余部分解释为 基本正则表达式。
  • (?e) 告诉 Tcl 将正则表达式的其余部分解释为 扩充正则表达式。
  • (?q) 告诉 Tcl 将正则表达式的其余部分解释为纯文本。「q」代表「quoted」。
  • (?s) 选择「非换行敏感比对」,这是默认值。「s」代表「single line」。在此模式中,点 和 否定字符类别 比对所有字符,包括换行符号。插入符号和美元符号 仅比对主旨字符串的最开始和最末尾。
  • (?p) 或 -linestop 激活「部分换行敏感比对」。在此模式中,点 和 否定字符类别 没有比对换行符号。插入符号和美元符号 仅比对主旨字符串的最开始和最末尾。
  • (?w) 或 -lineanchor 激活「反向部分换行敏感比对」。「w」代表「weird」。(别看我!我不是发明这个的人。)在此模式中,点 和 否定字符类别 比对所有字符,包括换行符号。插入符号和美元符号 比对换行符号之后和之前。
  • (?n) 或 -line 激活 Tcl 所谓的「换行敏感比对」。点 和 否定字符类别 没有比对换行符号。插入符号和美元符号 比对换行符号之后和之前。指定 (?n) 或 -line 与指定 (?pw) 或 -linestop -lineanchor 相同。
  • (?m) 是 (?n) 的历史同义词。

如果您在 Tcl 和其他编程语言中使用正则表达式,请在处理与换行相关的比对模式时小心。Tcl 的设计者发现 Perl 的 /m 和 /s 模式令人困惑。它们确实令人困惑,但至少 Perl 只有两个,而且它们只影响一件事。在 Perl 中,/m 或 (?m) 激活「多行模式」,这会让 插入符号和美元符号 在换行符号之后和之前比对。缺省情况下,它们只会在字符串的最开始和最后比对。在 Perl 中,/s 或 (?s) 激活「单行模式」。此模式会让 点 比对所有字符,包括换行符号。缺省情况下,它不会比对换行符号。Perl 没有模式修改器可以将换行符号排除在 取反字符类别 之外。在 Perl 中,[^a] 比对除了 a 之外的任何东西,包括换行符号。排除换行符号的唯一方法是写成 [^a\n]。Perl 的缺省比对模式就像 Tcl 的 (?p),除了取反字符类别的差异之外。

为什么要将 Tcl 与 Perl 进行比较?许多流行的正则表达式风格,例如 .NET、Java、PCRE 和 Python,都支持相同的 (?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 会传回套用替换后的字符串。

Tcl 有三種正規表示式風格
  • 简
  • 繁
  • En
關於正規表示式 » 正規表示式工具和實用程式 » Tcl 有三種正規表示式風格

正規表示式工具
grep
語言和函式庫
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
本網站上的更多資訊
簡介
正規表示式快速入門
正規表示式教學
替換字串教學
應用程式和語言
正規表示式範例
正規表示式參考
替換字串參考

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)傳遞給 regexp 和 regsub 命令以供某些模式使用。不支援 (?modes:regex) 風格的模式修改器跨度。模式修改器必須出現在正規表示法的開頭。它們會影響整個正規表示法。正規表示法中的模式修改器會覆寫命令開關。Tcl 支援這些模式

  • (?i) 或 -nocase 使正規表示法匹配大小寫不敏感。
  • (?c) 使正規表示法匹配大小寫敏感。此模式為預設值。
  • (?x) 或 -expanded 啟用 自由間距正規表示法語法。
  • (?t) 停用 自由間距正規表示法語法。此模式為預設值。“t”代表“緊密”,與“展開”相反。
  • (?b) 告訴 Tcl 將正規表示法的其餘部分解釋為 基本正規表示法。
  • (?e) 告訴 Tcl 將正規表示式的其餘部分解釋為 擴充正規表示式。
  • (?q) 告訴 Tcl 將正規表示式的其餘部分解釋為純文字。「q」代表「quoted」。
  • (?s) 選擇「非換行敏感比對」,這是預設值。「s」代表「single line」。在此模式中,點 和 否定字元類別 比對所有字元,包括換行符號。插入符號和美元符號 僅比對主旨字串的最開始和最末尾。
  • (?p) 或 -linestop 啟用「部分換行敏感比對」。在此模式中,點 和 否定字元類別 沒有比對換行符號。插入符號和美元符號 僅比對主旨字串的最開始和最末尾。
  • (?w) 或 -lineanchor 啟用「反向部分換行敏感比對」。「w」代表「weird」。(別看我!我不是發明這個的人。)在此模式中,點 和 否定字元類別 比對所有字元,包括換行符號。插入符號和美元符號 比對換行符號之後和之前。
  • (?n) 或 -line 啟用 Tcl 所謂的「換行敏感比對」。點 和 否定字元類別 沒有比對換行符號。插入符號和美元符號 比對換行符號之後和之前。指定 (?n) 或 -line 與指定 (?pw) 或 -linestop -lineanchor 相同。
  • (?m) 是 (?n) 的歷史同義詞。

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

為什麼要將 Tcl 與 Perl 進行比較?許多流行的正規表示式風格,例如 .NET、Java、PCRE 和 Python,都支援相同的 (?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 會傳回套用替換後的字串。

Tcl Has Three Regular Expression Flavors
  • 简
  • 繁
  • En
About Regular Expressions » Tools and Utilities for Regular Expressions » Tcl Has Three Regular Expression Flavors

Regex Tools
grep
Languages & Libraries
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
Databases
MySQL
Oracle
PostgreSQL
More on This Site
Introduction
Regular Expressions Quick Start
Regular Expressions Tutorial
Replacement Strings Tutorial
Applications and Languages
Regular Expressions Examples
Regular Expressions Reference
Replacement Strings Reference

Tcl Has Three Regular Expression Flavors

Tcl 8.2 and later support three regular expression flavors. The Tcl man pages dub them Basic Regular Expressions (BRE), Extended Regular Expressions (ERE) and Advanced Regular Expressions (ARE). BRE and ERE are mainly for backward compatibility with previous versions of Tcl. These flavor implement the two flavors defined in the POSIX standard. AREs are new in Tcl 8.2. They’re the default and recommended flavor. This flavor implements the POSIX ERE flavor, with a whole bunch of added features. Most of these features are inspired by similar features in Perl regular expressions.

Tcl’s regular expression support is based on a library developed for Tcl by Henry Spencer. This library has since been used in a number of other programming languages and applications, such as the PostgreSQL database and the wxWidgets GUI library for C++. Everything said about Tcl in this regular expressions tutorial applies to any tool that uses Henry Spencer’s Advanced Regular Expressions.

There are a number of important differences between Tcl Advanced Regular Expressions and Perl-style regular expressions. Tcl uses \m, \M, \y and \Y for word boundaries. Perl and most other modern regex flavors use \b and \B. In Tcl, these last two match a backspace and a backslash, respectively.

Tcl also takes a completely different approach to mode modifiers. The (?letters) syntax is the same, but the available mode letters and their meanings are quite different. Instead of adding mode modifiers to the regular expression, you can pass more descriptive switches like -nocase to the regexp and regsub commands for some of the modes. Mode modifier spans in the style of (?modes:regex) are not supported. Mode modifiers must appear at the start of the regex. They affect the whole regex. Mode modifiers in the regex override command switches. Tcl supports these modes:

  • (?i) or -nocase makes the regex match case insensitive.
  • (?c) makes the regex match case sensitive. This mode is the default.
  • (?x) or -expanded activates the free-spacing regexp syntax.
  • (?t) disables the free-spacing regexp syntax. This mode is the default. The “t” stands for “tight”, the opposite of “expanded”.
  • (?b) tells Tcl to interpret the remainder of the regular expression as a Basic Regular Expression.
  • (?e) tells Tcl to interpret the remainder of the regular expression as an Extended Regular Expression.
  • (?q) tells Tcl to interpret the remainder of the regular expression as plain text. The “q” stands for “quoted”.
  • (?s) selects “non-newline-sensitive matching”, which is the default. The “s” stands for “single line”. In this mode, the dot and negated character classes match all characters, including newlines. The caret and dollar match only at the very start and end of the subject string.
  • (?p) or -linestop enables “partial newline-sensitive matching”. In this mode, the dot and negated character classes do not match newlines. The caret and dollar match only at the very start and end of the subject string.
  • (?w) or -lineanchor enables “inverse partial newline-sensitive matching”. The “w” stands for “weird”. (Don’t look at me! I didn’t come up with this.) In this mode, the dot and negated character classes match all characters, including newlines. The caret and dollar match after and before newlines.
  • (?n) or -line enables what Tcl calls “newline-sensitive matching”. The dot and negated character classes do not match newlines. The caret and dollar match after and before newlines. Specifying (?n) or -line is the same as specifying (?pw) or -linestop -lineanchor.
  • (?m) is a historical synonym for (?n).

If you use regular expressions with Tcl and other programming languages, be careful when dealing with the newline-related matching modes. Tcl’s designers found Perl’s /m and /s modes confusing. They are confusing, but at least Perl has only two, and they both affect only one thing. In Perl, /m or (?m) enables “multi-line mode”, which makes the caret and dollar match after and before newlines. By default, they match at the very start and end of the string only. In Perl, /s or (?s) enables “single line mode”. This mode makes the dot match all characters, including line break. By default, it doesn’t match line breaks. Perl does not have a mode modifier to exclude line breaks from negated character classes. In Perl, [^a] matches anything except a, including newlines. The only way to exclude newlines is to write [^a\n]. Perl’s default matching mode is like Tcl’s (?p), except for the difference in negated character classes.

Why compare Tcl with Perl? Many popular regex flavors such as .NET, Java, PCRE and Python support the same (?m) and (?s) modifiers with the exact same defaults and effects as in Perl. Negated character classes work the same in all these languages and libraries. It’s unfortunate that Tcl didn’t follow Perl’s standard, since Tcl’s four options are just as confusing as Perl’s two options. Together they make a very nice alphabet soup.

If you ignore the fact that Tcl’s options affect negated character classes, you can use the following table to translate between Tcl’s newline modes and Perl-style newline modes. Note that the defaults are different. If you don’t use any switches, (?s). and . are equivalent in Tcl, but not in Perl.

TclPerlAnchorsDot
(?s) (default)(?s)Start and end of string onlyAny character
(?p)(default)Start and end of string onlyAny character except newlines
(?w)(?sm)Start and end of string, and at newlinesAny character
(?n)(?m)Start and end of string, and at newlinesAny character except newlines

Regular Expressions as Tcl Words

You can insert regular expressions in your Tcl source code either by enclosing them with double quotes (e.g. "my regexp") or by enclosing them with curly braces (e.g. {my regexp}. Since the braces don’t do any substitution like the quotes, they’re by far the best choice for regular expressions.

The only thing you need to worry about is that unescaped braces in the regular expression must be balanced. Escaped braces don’t need to be balanced, but the backslash used to escape the brace remains part of the regular expression. You can easily satisfy these requirements by escaping all braces in your regular expression, except those used as a quantifier. This way your regex will work as expected, and you don’t need to change it at all when pasting it into your Tcl source code, other than putting a pair of braces around it.

The regular expression ^\{\d{3}\\$ matches a string that consists entirely of an opening brace, three digits and one backslash. In Tcl, this becomes {^\{\d+{3}$\\}. There’s no doubling of backslashes or any sort of escaping needed, as long as you escape literal braces in the regular expression. { and \{ are both valid regular expressions to match a single opening brace in a Tcl ARE (and any Perl-style regex flavor, for that matter). Only the latter works correctly in a Tcl literal enclosed with braces.

Finding Regex Matches

It Tcl, you can use the regexp command to test if a regular expression matches (part of) a string, and to retrieve the matched part(s). The syntax of the command is:

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

Immediately after the regexp command, you can place zero or more switches from the list above to indicate how Tcl should apply the regular expression. The only required parameters are the regular expression and the subject string. You can specify a literal regular expression using braces as I just explained. Or, you can reference any string variable holding a regular expression read from a file or user input.

If you pass the name of a variable as an additional argument, Tcl stores the part of the string matched by the regular expression into that variable. Tcl does not set the variable to an empty string if the match attempt fails. If the regular expressions has capturing groups, you can add additional variable names to capture the text matched by each group. If you specify fewer variables than the regex has capturing groups, the text matched by the additional groups is not stored. If you specify more variables than the regex has capturing groups, the additional variables are set to an empty string if the overall regex match was successful.

The regexp command returns 1 if (part of) the string could be matched, and zero if there’s no match. The following script applies the regular expression my regex case insensitively to the string stored in the variable subjectstring and displays the result:

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

The regexp command supports three more switches that aren’t regex mode modifiers. The -all switch causes the command to return a number indicating how many times the regex could be matched. The variables storing the regex and group matches will store the last match in the string only.

The -inline switch tells the regexp command to return an array with the substring matched by the regular expression and all substrings matched by all capturing groups. If you also specify the -all switch, the array will contain the first regex match, all the group matches of the first match, then the second regex match, the group matches of the first match, etc.

The -start switch must be followed by a number (as a separate Tcl word) that indicates the character offset in the subject string at which Tcl should attempt the match. Everything before the starting position will be invisible to the regex engine. This means that \A will match at the character offset you specify with -start, even if that position is not at the start of the string.

Replacing Regex Matches

With the regsub command, you can replace regular expression matches in a string.

regsub ?switches? regexp subject replacement ?resultvar?

Just like the regexp command, regsub takes zero or more switches followed by a regular expression. It supports the same switches, except for -inline. Remember to specify -all if you want to replace all matches in the string.

The argument after the regexp should be the replacement text. You can specify a literal replacement using the brace syntax, or reference a string variable. The regsub command recognizes a few metacharacters in the replacement text. You can use \0 as a placeholder for the whole regex match, and \1 through \9 for the text matched by one of the first nine capturing groups. You can also use & as a synonym of \0. Note that there’s no backslash in front of the ampersand. & is substituted with the whole regex match, while \& is substituted with a literal ampersand. Use \\ to insert a literal backslash. You only need to escape backslashes if they’re followed by a digit, to prevent the combination from being seen as a backreference. Again, to prevent unnecessary duplication of backslashes, you should enclose the replacement text with braces instead of double quotes. The replacement text \1 becomes {\1} when using braces, and "\\1" when using quotes.

If you pass a variable reference as the final argument, that variable receives the string with the replacements applied, and regsub returns an integer indicating the number of replacements made. Tcl 8.4 and later allow you to omit the final argument. In that case regsub returns the string with the replacements applied.

©2015-2025 艾丽卡 support@alaica.com