正则表达式

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, var1 = $var1"

 => match = willvar1 = 

set result [regexp {([a-z]+) ([a-z]+) ([a-z]+)} $sample mStr var1 var2 var3]  #匹配字母a-z

 => 1

 puts "maStr = $maStr, var1 = $var1, var2 = $var2, var3 = $var3"

 => 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, var1 = $var1, var2 = $var2, var3 = $var3"

 => 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, var1 = $var1, var2 = $var2, var3 = $var3"

 => 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 可以是普通字符,也可以含有&\xx 是一个数字)。当是这两个特殊字符时, &\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; var1 = $var1; var2 = $var2"

 => match = allow I; var1 = ; var2 =   #没有指定子模式,只返回整个匹配子串,匹配变量var1和var2为空

regexp {([a-z]+) ([A-Z].)} "allow In" match var1 var2

puts "match = $match; var1 = $var1; var2 = $var2"

 =>  match = allow In; var1 = allow; var2 = In

3.2.7 反斜杠引用

使用反斜杠 \ 可以关闭特殊字符的特殊含义,从而将这些字符作为普通字符对待,这些特殊字符有“ . * ? + [ ] ( ) ^ $ | \” 。 

比如要匹配? 则需要写为:\? 

但是,如果这种特殊字符是用在方括号表达式内,就没有必要使用反斜杠处理(除反斜杠自身),如下面的两种方式效果相同:

  • ( \ + | \ ? )

  • [ + | ?]   

3.3 高级正则表达式AREs

posted @ 2024-04-17 22:22  小熊酱  阅读(4)  评论(0编辑  收藏  举报