正则表达式
1. regexp 命令
regexp 匹配正则表达式与字符串,它的语法为:
- regexp ?switches ? exp string ?matchvar? ?subMatchVar ... subMatchVar?
regexp 命令比较字符串 string 是否与正则表达式 exp 部分或者全部匹配,并可以将字符串中的子字符串提取出来。如果字符串的某个子字符串和正则表达式匹配,则返回1,否则返回 0。
如果在 string 变量后面,还有其它的变量(称之为匹配变量, match variables),则这些变量就保存了那些与正则表达式匹配的子字符串信息(如可能是子字符串的实际内容,或者是界定子字符串的起始、结束的索引数字)。 matchVar 保存了匹配 exp 的字符串,而 subMatchVar 依次存放了和 exp 各个中单个括号语法(子模式)匹配的子字符串。
regexp 中的 switches 是命令开关选项,这些选项主要有:
选项 | 说明 |
- nocase | exp 中的小写字符可以匹配 string 中的大写和小写字符 |
- indices | 返回界定 string 中匹配区间起始、结束的索引数值。否则返回匹配区间内字符串本身 |
- expanded | 使用扩展语法 |
- line | 等价于同时指定-lineanchor 和-linestop |
- lineanchor | 将^和$的行为改为面向行的方式 |
- linestop | 将匹配方式改变成和字符类不匹配换行符 |
- about | 适用于调试,返回有关模式的信息而不是试图与输入进行匹配 |
- all | 让正则表达式在 string 中匹配所有的匹配子字符串,返回匹配次数,而且将最后一次匹配结果存入匹配变量 |
- inline | 将原来存放在匹配变量中的值以列表的形式返回,如果同时使用了-all,则返回所有满足匹配结果的值的列表。 |
- start index | 用 index 指定 exp 在 string 中起始匹配位置。如果使用了-indices,返回的索引是从输入字符串 string 的绝对起始位置算起而不是从 index 指定位置算起 |
-- | 结束选项,如果表达式以-开始, 则需先用此选项 |
regexp示例:
set sample "Where there is a will, There is a way."
=> Where there is a will, There is a way.
set result [regexp {will} $sample match var1]
=> 1
puts "match =
=> match = will,var1 =
set result [regexp {([a-z]+) ([a-z]+) ([a-z]+)} $sample mStr var1 var2 var3] #匹配字母a-z
=> 1
puts "maStr =
=> maStr = here there is, var1 = here, var2 = there, var3 = is
带有 nocase 选项的 regexp 命令 :
set result [regexp -nocase {([a-z]+) ([a-z]+) ([a-z]+)} $sample mStr var1 var2 var3]
=> 1
puts "maStr =
=> maStr = Where there is, var1 = Where, var2 = there, var3 = is
指明需要返回索引数值而不是字符串本身:
set result [regexp -indices {([a-z]+) ([a-z]+) ([a-z]+)} $sample mStr var1 var2 var3]
=> 1
puts "maStr =
=> maStr = 1 13, var1 = 1 4, var2 = 6 10, var3 = 12 13
2. regsub 命令
regsub 命令基于正则表达式完成字符串匹配和替换。
语法:
- regsub ?switches? exp string subSpec varName
switches 是命令开关选项,主要有:
-
开关选项-nocase、 -expanded、 -line、 -linestop、 -lineanchor、 -start index 和--与 regexp 命令开关选项作用相同
- -all 对所有满足匹配条件的字符串范围进行替换,返回匹配和替换的次数。没有此选项时,只匹配第一个满足匹配条件的匹配范围并用 subSpec 替换之。
替换模式 subSpec 可以是普通字符,也可以含有&和\x( x 是一个数字)。当是这两个特殊字符时, &和\x 就会被替换成与 exp 中的对应模式匹配的 string 中的匹配范围内的字符。
varName 存放替换后的字符串。
示例:
set sample "Where there is a will, There is a way."
=>Where there is a will, There is a way.
regsub "way" $sample "lawsuit" sample2
=> 1
puts "New:$sample2"
=> New:Where there is a will, There is a lawsuit.
使用&和\0 的 subSpec:
regsub {([a-z]+) ([a-z]+)} $sample {"-&- lawsuit -\1- -\2-"} sample2
puts "New:$sample2"
=> New:W"-here there- lawsuit -here- -there-" is a wail, There is a way.
3. 正则表达式 Regular Expressions
3.1 分支和原子
正则表达式由一个或多个分支组成,分支之间用符号 | 来相连。每个分支则由零个或者多个原子组成。这些原子的形式主要有(标 AREs 为 高级正则表达式支持功能):
-(re) | 圆括号子表达式,并报告捕获子串 |
-(?:re) | 同上,但屏蔽报告( AREs) |
-() | 空圆括号子表达式,捕获空字符串并报告 |
-(?:) | 同上,但屏蔽报告( AREs) |
- [char] | 方括号表达式,匹配指定的字符集中任意一个字符 |
- . | 匹配中任意一个字符 |
- \k | (k 是非字母数字字符)将字符看作普通字符(关闭特殊解释),如\匹配反斜杠 |
- \c | (c 是字母数字字符), AREs 的换码(escape)语法( AREs) |
- { | 当后跟非数字字符时,表示匹配左花括弧;跟数字时,表示边界 (bound,AREs) |
- x | x 是单个字符(包含空格),匹配字符本身 |
3.2 基本语法
3.2.1 匹配字符
大多数字符可以用来直接作为原子和自身进行匹配,如下例中的表达式匹配一个 a 和 b 字符组合:
regexp {ab} "This text talks about China." match
=> 1
puts $match
=> ab
大多数字符可以用来直接作为原子和自身进行匹配,如下例中的表达式匹配一个 a 和 b 字符组合:
regexp {a.} "This text talks about China." match
=> 1
puts $match
=> al
3.2.2 限定匹配
字符匹配可以发生在字符串中的任何位置,一个模式不必分配整个字符串,在匹配地字符前面和后面都可以有未匹配的字符。可以使用定位符( ^和$)来指定匹配位置: ^将匹配限制在字符串起始位置, $则限制在结尾。可以同时使用这两个符号来匹配整个字符串。如下例匹配所有以字母 T 或 M 开始的字符串:
regexp {^[TM]+} "This test talks about Chinese." match
=> 1
regexp {^[TM]+} "Man and Woman" match
puts $match
=> M
regexp {^[T]+} "Hello" match
=> 0
定位符是相对整个输入字符串来说的,而忽略字符串内的换行符, ARE 支持将^和$设置为面向行的选项,并增加字符串起始和终止位置定位符\A 和\Z。对于 ARE,还有其他限定字符,即正前瞻和负前瞻。
3.2.3 方括号表达式与字符集
通过使用方括号括起多个字符的方式[xyz],来指定匹配字符的范围(1)。这一方法使正则表达式可以对字符集中的任意一个字符进行匹配。
regexp {[Hh]ello} "He said hello to me." match
=> 1
puts $match
=> hello
regexp {[Hh]ello} "He said Hello to me." match
=> 1
puts $match
=> Hello
regexp -indices {-[a-d A-D]} "Effort is applied" match #匹配a到d和A到D之间的任意一个字符,将匹配位置放入match
=> 1
puts $match
=> 10 10
regexp -all -inline {[^a-d A-D]} "Effort is applied" #匹配所有非a到d和A到D之间的任意一个字符
=> E f f o rt {} i s { } p p l i e #单词之间的空格被{}显示表示
3.2.4 匹配分支
用 | 可以连接多个匹配分支,可以同时用来测试多个匹配模式。可以将 | 看作或运算,即只要字符串与一个分支匹配即会进行匹配。如 Hello | hello 即表示或者与 hello 匹配,或者与Hello 匹配。
上面这个模式还等价于:
(h | H)ello
或者是:
[h | H]ello
3.2.5 量词
一个原子后面可以跟一个量词,来指定进行多次匹配。这些量词及含义有:
-
* 表示重复零次或多次
-
+ 表示重复一次或多次
-
?表示重复零次或一次
例如:
-
ba* 表示匹配一个 b 后跟有零个或者多个字符 a 的字符串;
-
(ab)+ 表示匹配一个或多个ab序列的字符串;
-
.* 可以匹配任意字符串或空字符串;
3.2.6 子模式与匹配报告捕获
在正则表达式中,可以用圆括号来指定多个匹配子模式。如{( exp A)( exp B) }指定了两个匹配子模式(注意子模式之间还有一个空格,这个空格参与匹配)。与圆括号内部匹配的范围内的字符会被保存在匹配变量中。如果不用子模式的话,正则表达式只返回与整个正则表达式匹配范围内的字符串,而不能象字模式那样捕获更细致匹配子字符串。
regexp {[a-z]+ [A-Z]+} "allow In" match var1 var2
=> 1
puts "match =
=> match = allow I; var1 = ; var2 = #没有指定子模式,只返回整个匹配子串,匹配变量var1和var2为空
regexp {([a-z]+) ([A-Z].)} "allow In" match var1 var2
puts "match =
=> match = allow In; var1 = allow; var2 = In
3.2.7 反斜杠引用
使用反斜杠 \ 可以关闭特殊字符的特殊含义,从而将这些字符作为普通字符对待,这些特殊字符有“ . * ? + [ ] ( ) ^ $ | \” 。
比如要匹配? 则需要写为:\?
但是,如果这种特殊字符是用在方括号表达式内,就没有必要使用反斜杠处理(除反斜杠自身),如下面的两种方式效果相同:
-
( \ + | \ ? )
-
[ + | ?]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端