快速入门
教程
工具和语言
示例
参考
书评
正则表达式工具
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 库(适用于 C++)。此 正则表达式教程 中关于 Tcl 的所有内容都适用于任何使用 Henry Spencer 的高级正则表达式的工具。

Tcl 高级正则表达式和 Perl 风格正则表达式之间有许多重要区别。Tcl 使用 \m\M\y\Y 表示 词界。Perl 和大多数其他现代正则表达式风格使用 \b\B。在 Tcl 中,后两个分别匹配退格符和反斜杠。

Tcl 还采用了完全不同的方法来处理 模式修饰符(?letters) 语法相同,但可用的模式字母及其含义却大不相同。您可以向 regexpregsub 命令传递更具描述性的开关(如 -nocase),以代替向正则表达式添加模式修饰符,从而实现某些模式。不支持 (?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 ?switches? regexp subject replacement ?resultvar?

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 |