发布于2026-06-29 阅读(0)
扫一扫,手机访问
正则表达式在Perl中堪称字符串处理的灵魂利器。简单来说,模式(Pattern)就是你想在字符串中寻找的特定字符序列,通常用反斜线包裹起来,比如/def/就是匹配字符串中的"def"。它的典型用法是和split函数配合,把一行文本按某种模式拆分成单词数组:@array = split(/ /, $line);。这个基础操作打天下无数,但真正的威力远不止于此。

=~是Perl匹配的“试金石”——它检验某个字符串是否包含指定的模式。例如$result = $var =~ /abc/;,如果在$var中找到了"abc",就返回非零值(true),否则返回0(false)。与之相反的!~则在匹配失败时返回真。这两个操作符最常用的场景就是条件判断,比如:
Perl在模式里加入了一堆“特工级”字符,让匹配变得灵活到飞起。下面一个个来拆解。
+表示“一个或多个”相同的字符。比如/de+f/能匹配def、deef、deeeeef……它会“贪婪”地吃掉尽可能多的相同字符。举个例子,/ab+/在字符串"abbc"中匹配的是"abb"而不是"ab"。这个特性在处理多空格分割时特别实用:@array = split (/ +/, $line);。不过有个小坑:split函数每次遇到分割模式都会开始一个新单词,如果$line以空格开头,那么@array的第一个元素就是空元素。如果$line里只有空格,@array就是空数组。另外注意,TAB字符会被当成一个单词,需要单独处理。
[]表示匹配括号内任意一个字符。/a[0123456789]c/匹配"a"加任意数字加"c"的字符串。和+联用:/d[eE]+f/能匹配def、dEf、deef、dEef、dEEEeeeEef等。而^在方括号内表示“非”,比如/d[^deE]f/匹配"d"加一个非"e"字符加"f"的字符串。
这两个字符和+类似,但*匹配0个、1个或多个相同字符,?则匹配0个或1个。例如/de*f/能匹配df、def、deeeef等;/de?f/只匹配df或def。
如果需要在模式里匹配那些有特殊意义的字符(比如+、*、?等),必须在它们前面加上反斜线。例如/\*\+/中的*就是字面意义上的星号,而不是“一个或多个”。反斜线本身也要转义为\/。在Perl 5中还可以用\Q和\E这对命令来批量转义。
前面提到的/a[0123456789]c/可以简写为/a[0-9]c/,类似地[a-z]表示任意小写字母,[A-Z]表示任意大写字母。任意大小写字母和数字的集合就是/[0-9a-zA-Z]/。
锚用于锁定匹配的位置:
^或\A:仅匹配字符串开头$或\Z:仅匹配字符串结尾\b:匹配单词边界\B:匹配单词内部举个例子:/^def/只匹配以"def"开头的字符串;/def$/只匹配以"def"结尾的;/^def$/则只匹配字符串"def"本身。在多行匹配中,\A和\Z与^、$的行为略有不同。
实战:检测变量名的类型:
关于\b的更多用法:/\bdef/匹配以"def"开头的单词(如def、defghi),但不匹配abcdef;/def\b/匹配以"def"结尾的单词(如def、abcdef),但不匹配defghi;/\bdef\b/只匹配孤零零的"def"。注意/\bdef/可以匹配$defghi,因为$不被视为单词的一部分。
\B则相反:/\Bdef/匹配abcdef,但不匹配def;/def\B/匹配defghi;/\Bdef\B/匹配cdefg、abcdefghi这类。
模式里可以直接使用Perl变量。比如要把一句文本按空白拆成单词:
$pattern = "[\t ]+";
@words = split(/$pattern/, $line);
Perl提供了一组快捷转义符,省去写方括号的麻烦:
\d:任意数字,等价于[0-9]\D:非数字,等价于[^0-9]\w:任意单词字符(包括下划线),等价于[_0-9a-zA-Z]\W:非单词字符,等价于[^_0-9a-zA-Z]\s:空白字符(空格、制表符、换行等),等价于[ \t\r\n\f]\S:非空白字符,等价于[^ \t\r\n\f]例如/[\da-z]/匹配任意数字或小写字母。
.(点号)匹配除换行符外的任意字符,通常和*一起使用来匹配任意长度的内容。
{}用于精确控制重复次数。例如/de{1,3}f/匹配def、deef、deeef;/de{3}f/只匹配deeef;/de{3,}f/匹配d和f之间至少3个e;/de{0,3}f/匹配最多3个e。
|表示“或”,比如/def|ghi/匹配"def"或"ghi"。它非常适用于判断多种合法格式,比如检测一个数是否是合法整数:
if ($number =~ /^-?\d+$|^-?0[xX][\da-fA-F]+$/) {
print ("$number is a legal integer.n");
} else {
print ("$number is not a legal integer.n");
}
这里^-?\d+$匹配十进制,^-?0[xX][\da-fA-F]+$匹配十六进制。
当模式中某一部分重复出现时,可以用括号把它包起来,然后用\n(n为数字)来引用它。例如/\d{2}([\W])\d{2}\1\d{2}/可以匹配"12-05-92"、"26.11.87"、"07 04 92"等——注意\1引用了前面捕获到的那个分隔符。这和/(\d{2})([\W])\1\2\1/不同,后者只能匹配形如"17-17-17"的字符串,而不是"17-05-91"。
各种特殊字符和转义符也有优先级,类似于数学运算符:
() 模式内存(最高优先级)+ * ? {} 出现次数^ $ \b \B 锚| 选项(最低优先级)默认模式定界符是/,但可以用m来自由指定。比如m!/u/jqpublic/perl/prog1!等价于/\/u\/jqpublic\/perl\/prog1/,避免了大量转义。不过如果用单引号做定界符,模式内不会进行变量替换;如果用了特殊字符做定界符,它本身的特殊功能也就失效了。
模式匹配成功后,括号捕获的内容会存到$1、$2……中,而整个匹配的内容存在$&中。看个例子:
选项可以附加在模式定界符后面,用来改变匹配行为:
g:全局匹配,找所有可能的模式i:忽略大小写m:将字符串视为多行o:只对模式中的变量替换一次s:将字符串视为单行(让.匹配换行符)x:忽略模式中的空白(允许加空格和注释)输出:
使用g选项时,可以用pos函数来手动控制下次匹配的起始偏移量:
$offset = pos($string);
pos($string) = $newoffset;
/de/i能匹配de、dE、De、DE,大小写通吃。
启用m后,^不仅匹配字符串起始,还匹配每一行的开头;$匹配每一行的结尾。
这里/o让$var的替换只执行一次,所以实际上每次匹配的都是/1/(第一次$var的值)。这个选项在循环中能提升性能,但要小心语义是否符合预期。
/a.*bc/s可以匹配"axxxxx\nxxxxbc"这样的跨行字符串,而普通的/a.*bc/则不行(因为.默认不匹配换行)。
/\d{2} ([\W]) \d{2} \1 \d{2}/x等价于/\d{2}([\W])\d{2}\1\d{2}/,加了空格便于阅读。
语法:s/pattern/replacement/。它将字符串中匹配pattern的部分替换成replacement。例如:
$string = "abc123def";
$string =~ s/123/456/; # now $string = "abc456def";
替换部分可以使用模式次序变量$n,比如s/(\d+)/[$1]/。但注意替换部分不支持模式特殊字符(如*、+等),若写成s/abc/[def]/就是把"abc"换成"[def]"这个字面字符串。
替换操作符的选项和匹配操作符基本相同,多了一个e选项:
g:替换所有匹配i:忽略大小写e:将替换字符串当作Perl表达式执行,结果作为替换内容m:多行o:仅赋值一次s:单行x:忽略空白e选项的妙处:
$string = "0abc1";
$string =~ s/[a-zA-Z]+/$& x 2/e; # now $string = "0abcabc1"
这里$&是匹配到的"abc",乘以2就变成了"abcabc"。
它提供了另一种替换方式:tr/string1/string2/。效果是一对一替换:把string1中的第一个字符换成string2中的第一个,第二个换成第二个,以此类推。例如:
$string = "abcdefghicba";
$string =~ tr/abc/def/; # now string = "defdefghifed"
规则说明:如果string1比string2长,多出来的字符换成string2的最后一个字符;如果string1中有重复字符,以第一次出现为准。
翻译操作符的选项:
c:翻译所有未在string1中指定的字符d:删除所有在string1中指定的字符s:把多个连续相同的输出字符压缩成一个几个经典用法:$string =~ tr/\d/ /c; 把非数字字符替换为空格;$string =~ tr/\t //d; 删除所有制表符和空格;$string =~ tr/0-9/ /cs; 把数字之间的其他字符压缩成一个空格。
Perl还提供了一些超出传统正则的能力,语法是(?cpattern),其中c是一个控制字符。
通常括号里的子模式会占用内存,如果想避免,可以用(?:...)。比如/(?:a|b|c)(d|e)f\1/中的\1引用的是(d|e)捕获的内容,而不是(a|b|c)的。
选项i、m、s、x除了写在外面,也可以直接嵌在模式中:/(?i)pattern/等价于/pattern/i。
pattern(?=string)表示匹配后面紧跟string的pattern,但string本身不包含在最终匹配结果中。否定形式是(?!string),表示后面不是string。例如:
$string = "25abc8";
$string =~ /abc(?=[0-9])/;
$matched = $&;; # $matched 是 "abc",而不是 "abc8"
在x选项下可以写注释,也可以直接用(?#...)在任何位置加注释:
if ($string =~ /(?i)[a-z]{2,3}(?# match two or three alphabetic characters)/ {
...
}
为了方便查阅,整理了一份速查对照表。这是一份非常实用的文字处理模式常用语法清单(Regular Expression),笔者把它列在这里,方便你在写脚本时快速参考:
| 语法 | 说明 |
|---|---|
| . | 除换行符外,匹配任意一个字符 |
| x? | 0个或1个x字符 |
| x* | 0个或多个x字符 |
| .* | 0个或多个任意字符 |
| x+ | 1个或多个x字符 |
| .+ | 1个或多个任意字符 |
| {m} | 恰好m个指定字符 |
| {m,n} | m到n个指定字符 |
| {m,} | 至少m个指定字符 |
| [] | 匹配括号内的任意一个字符 |
| [^] | 匹配不在括号内的任意一个字符 |
| [0-9] | 任意数字 |
| [a-z] | 任意小写字母 |
| [^0-9] | 任意非数字 |
| [^a-z] | 任意非小写字母 |
| ^ | 匹配字符串开头 |
| $ | 匹配字符串结尾 |
| \d | 数字,等价于[0-9] |
| \d+ | 一个或多个数字,等价于[0-9]+ |
| \D | 非数字,等价于[^0-9] |
| \D+ | 一个或多个非数字,等价于[^0-9]+ |
| \w | 单词字符(字母、数字、下划线),等价于[a-zA-Z0-9_] |
| \w+ | 一个或多个单词字符,等价于[a-zA-Z0-9_]+ |
| \W | 非单词字符,等价于[^a-zA-Z0-9_] |
| \W+ | 一个或多个非单词字符,等价于[^a-zA-Z0-9_]+ |
| \s | 空白字符(空格、制表符、换行等),等价于[ \t\n\r\f] |
| \s+ | 一个或多个空白字符,等价于[ \t\n\r\f]+ |
| \S | 非空白字符,等价于[^ \t\n\r\f] |
| \S+ | 一个或多个非空白字符,等价于[^ \t\n\r\f]+ |
| \b | 单词边界 |
| \B | 非单词边界(单词内部) |
| a|b|c | 匹配a或b或c中的任意一个 |
| abc | 匹配字符串"abc" |
| (pattern) | 捕获匹配的内容到$1、$2…… |
| /pattern/i | 忽略大小写 |
| \特殊字符 | 转义,使特殊字符失去特殊含义 |
这里列一些常见的模式及其匹配效果,方便初学者对照练习:
| 范例 | 说明 |
|---|---|
| /perl/ | 找到含有"perl"的字符串 |
| /^perl/ | 找到以"perl"开头的字符串 |
| /perl$/ | 找到以"perl"结尾的字符串 |
| /c|g|i/ | 找到含有c或g或i的字符串 |
| /cg{2,4}i/ | c后面跟2~4个g,再跟i |
| /cg{2,}i/ | c后面跟至少2个g,再跟i |
| /cg{2}i/ | c后面跟恰好2个g,再跟i |
| /cg*i/ | c后面跟0或多个g,再跟i(等同于/cg{0,}i/) |
| /cg+i/ | c后面跟1个或多个g,再跟i(等同于/cg{1,}i/) |
| /cg?i/ | c后面跟0或1个g,再跟i(等同于/cg{0,1}i/) |
| /c.i/ | c后面跟任意一个字符,再跟i |
| /c..i/ | c后面跟任意两个字符,再跟i |
| /[cgi]/ | 匹配c、g、i中任意一个字符 |
| /[^cgi]/ | 匹配非c、g、i的任意字符 |
| /d/ | 匹配一个数字 |
| /d+/ | 一个或多个数字 |
| /D/ | 匹配一个非数字 |
| /D+/ | 一个或多个非数字 |
| /w/ | 匹配一个单词字符 |
| /w+/ | 一个或多个单词字符 |
| /W/ | 匹配一个非单词字符 |
| /W+/ | 一个或多个非单词字符 |
| /s/ | 匹配一个空白字符 |
| /s+/ | 一个或多个空白字符 |
| /S/ | 匹配一个非空白字符 |
| /S+/ | 一个或多个非空白字符 |
| /\*/ | 匹配星号本身(转义) |
| /abc/i | 匹配"abc"(忽略大小写) |
在Perl编程中,=~和!~这两个运算符,以及s///和tr///这两个函数,是和/pattern/搭配最频繁的组合。把它们用熟练了,处理字符串就可以得心应手,写CGI程序时更是如虎添翼。
上一篇:Perl中的控制结构学习笔记
下一篇:Perl中的文件读写学习笔记
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8