- Perl 基础知识
- Perl - 主页
- Perl - 简介
- Perl - 环境
- Perl - 语法概述
- Perl - 数据类型
- Perl - 变量
- Perl - 标量
- Perl - 数组
- Perl - 哈希
- Perl - IF...ELSE
- Perl - 循环
- Perl - 运算符
- Perl - 日期和时间
- Perl - 子例程
- Perl - 参考资料
- Perl - 格式
- Perl - 文件 I/O
- Perl - 目录
- Perl - 错误处理
- Perl - 特殊变量
- Perl - 编码标准
- Perl - 正则表达式
- Perl - 发送电子邮件
- Perl 高级
- Perl - 套接字编程
- Perl - 面向对象
- Perl - 数据库访问
- Perl - CGI 编程
- Perl - 包和模块
- Perl - 流程管理
- Perl - 嵌入式文档
- Perl - 函数参考
- Perl 有用资源
- Perl - 问题与解答
- Perl - 快速指南
- Perl - 有用的资源
- Perl - 讨论
Perl - 正则表达式
正则表达式是定义您正在查看的一个或多个模式的字符串。Perl 中正则表达式的语法与其他正则表达式支持程序(例如sed、grep和awk )中的语法非常相似。
应用正则表达式的基本方法是使用模式绑定运算符 =~ 和! ~。第一个运算符是测试和赋值运算符。
Perl 中有三个正则表达式运算符。
- 匹配正则表达式 - m//
- 替换正则表达式 - s///
- 音译正则表达式 - tr///
每种情况下的正斜杠都充当您指定的正则表达式 (regex) 的分隔符。如果您对任何其他分隔符感到满意,那么您可以使用它来代替正斜杠。
匹配运算符
匹配运算符 m// 用于将字符串或语句与正则表达式匹配。例如,要将字符序列“foo”与标量 $bar 进行匹配,您可以使用如下语句 -
#!/usr/bin/perl $bar = "This is foo and again foo"; if ($bar =~ /foo/) { print "First time is matching\n"; } else { print "First time is not matching\n"; } $bar = "foo"; if ($bar =~ /foo/) { print "Second time is matching\n"; } else { print "Second time is not matching\n"; }
当执行上面的程序时,它会产生以下结果 -
First time is matching Second time is matching
m// 实际上与 q// 运算符系列的工作方式相同。您可以使用自然匹配字符的任意组合来充当表达式的分隔符。例如,m{}、m() 和 m>< 都是有效的。所以上面的例子可以重写如下 -
#!/usr/bin/perl $bar = "This is foo and again foo"; if ($bar =~ m[foo]) { print "First time is matching\n"; } else { print "First time is not matching\n"; } $bar = "foo"; if ($bar =~ m{foo}) { print "Second time is matching\n"; } else { print "Second time is not matching\n"; }
如果分隔符是正斜杠,则可以从 m// 中省略 m,但对于所有其他分隔符,必须使用 m 前缀。
请注意,如果表达式匹配,则整个匹配表达式(即 =~ 或 !~ 左侧的表达式以及匹配运算符)将返回 true(在标量上下文中)。因此声明 -
$true = ($foo =~ m/foo/);
如果 $foo 与正则表达式匹配,则将 $true 设置为 1;如果匹配失败,则将 $true 设置为 0。在列表上下文中,匹配返回任何分组表达式的内容。例如,当从时间字符串中提取小时、分钟和秒时,我们可以使用 -
my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
匹配运算符修饰符
匹配运算符支持其自己的一组修饰符。/g 修饰符允许全局匹配。/i 修饰符将使匹配不区分大小写。这是修饰符的完整列表
先生。 | 修改器和描述 |
---|---|
1 | 我 使匹配不区分大小写。 |
2 | 米 指定如果字符串包含换行符或回车符,则 ^ 和 $ 运算符现在将匹配换行符边界,而不是字符串边界。 |
3 | 哦 仅对表达式求值一次。 |
4 | s 允许使用 . 匹配换行符。 |
5 | X 允许您在表达式中使用空格以保持清晰。 |
6 | G 全局查找所有匹配项。 |
7 | CG 即使全局匹配失败后也允许继续搜索。 |
仅匹配一次
还有一个更简单版本的匹配运算符 - ?PATTERN? 操作员。这基本上与 m// 运算符相同,只是它在每次调用重置之间搜索的字符串中仅匹配一次。
例如,您可以使用它来获取列表中的第一个和最后一个元素 -
#!/usr/bin/perl @list = qw/food foosball subeo footnote terfoot canic footbrdige/; foreach (@list) { $first = $1 if /(foo.*?)/; $last = $1 if /(foo.*)/; } print "First: $first, Last: $last\n";
当执行上面的程序时,它会产生以下结果 -
First: foo, Last: footbrdige
正则表达式变量
正则表达式变量包括$,它包含最后一个分组匹配匹配的内容;$&,包含整个匹配的字符串;$`,包含匹配字符串之前的所有内容;和$',其中包含匹配字符串之后的所有内容。以下代码演示了结果 -
#!/usr/bin/perl $string = "The food is in the salad bar"; $string =~ m/foo/; print "Before: $`\n"; print "Matched: $&\n"; print "After: $'\n";
当执行上面的程序时,它会产生以下结果 -
Before: The Matched: foo After: d is in the salad bar
替换运算符
替换运算符 s/// 实际上只是匹配运算符的扩展,它允许您用一些新文本替换匹配的文本。运算符的基本形式是 -
s/PATTERN/REPLACEMENT/;
PATTERN 是我们正在查找的文本的正则表达式。REPLACMENT 是我们想要用来替换找到的文本的文本或正则表达式的规范。例如,我们可以使用以下正则表达式将所有出现的狗替换为猫-
#/user/bin/perl $string = "The cat sat on the mat"; $string =~ s/cat/dog/; print "$string\n";
当执行上面的程序时,它会产生以下结果 -
The dog sat on the mat
替换运算符修饰符
以下是与替换运算符一起使用的所有修饰符的列表。
先生。 | 修改器和描述 |
---|---|
1 | 我 使匹配不区分大小写。 |
2 | 米 指定如果字符串包含换行符或回车符,则 ^ 和 $ 运算符现在将匹配换行符边界,而不是字符串边界。 |
3 | 哦 仅对表达式求值一次。 |
4 | s 允许使用 . 匹配换行符。 |
5 | X 允许您在表达式中使用空格以保持清晰。 |
6 | G 将所有出现的找到的表达式替换为替换文本。 |
7 | e 像 Perl 语句一样评估替换,并使用其返回值作为替换文本。 |
翻译操作员
翻译与替换原则类似但不相同,但与替换不同的是,翻译(或音译)不使用正则表达式来搜索替换值。翻译运算符是 -
tr/SEARCHLIST/REPLACEMENTLIST/cds y/SEARCHLIST/REPLACEMENTLIST/cds
翻译会将 SEARCHLIST 中出现的所有字符替换为 REPLACMENTLIST 中相应的字符。例如,使用“猫坐在垫子上”。我们在本章中使用的字符串 -
#/user/bin/perl $string = 'The cat sat on the mat'; $string =~ tr/a/o/; print "$string\n";
当执行上面的程序时,它会产生以下结果 -
The cot sot on the mot.
还可以使用标准 Perl 范围,允许您通过字母或数值指定字符范围。要更改字符串的大小写,您可以使用以下语法代替uc函数。
$string =~ tr/a-z/A-Z/;
翻译运算符修饰符
以下是与翻译相关的运算符列表。
先生。 | 修改器和描述 |
---|---|
1 | C 补充搜索列表。 |
2 | d 删除已找到但未替换的字符。 |
3 | s 挤压重复的替换字符。 |
/d 修饰符删除与 SEARCHLIST 匹配但在 REPLACMENTLIST 中没有相应条目的字符。例如 -
#!/usr/bin/perl $string = 'the cat sat on the mat.'; $string =~ tr/a-z/b/d; print "$string\n";
当执行上面的程序时,它会产生以下结果 -
b b b.
最后一个修饰符 /s 删除了被替换的重复字符序列,因此 -
#!/usr/bin/perl $string = 'food'; $string = 'food'; $string =~ tr/a-z/a-z/s; print "$string\n";
当执行上面的程序时,它会产生以下结果 -
fod
更复杂的正则表达式
您不仅需要匹配固定字符串。事实上,您可以通过使用更复杂的正则表达式来匹配您想要的任何内容。这是一个快速备忘单 -
下表列出了 Python 中可用的正则表达式语法。
先生。 | 图案及描述 |
---|---|
1 | ^ 匹配行首。 |
2 | $ 匹配行尾。 |
3 | 。 匹配除换行符之外的任何单个字符。使用 m 选项也可以匹配换行符。 |
4 | [...] 匹配括号中的任何单个字符。 |
5 | [^...] 匹配不在括号中的任何单个字符。 |
6 | * 匹配 0 次或多次出现的前面表达式。 |
7 | + 匹配前面的表达式出现 1 次或多次。 |
8 | ? 匹配前面表达式的 0 或 1 次出现。 |
9 | {n} 精确匹配前面表达式的 n 次出现。 |
10 | {n,} 匹配 n 次或多次出现的前面表达式。 |
11 | {n,米} 匹配前面表达式至少出现 n 次、最多出现 m 次。 |
12 | 一个| 乙 匹配 a 或 b。 |
13 | \w 匹配单词字符。 |
14 | \W 匹配非单词字符。 |
15 | \s 匹配空白。相当于[\t\n\r\f]。 |
16 | \S 匹配非空白。 |
17 号 | \d 匹配数字。相当于[0-9]。 |
18 | \D 匹配非数字。 |
19 | \A 匹配字符串的开头。 |
20 | \Z 匹配字符串结尾。如果存在换行符,则它会在换行符之前匹配。 |
21 | \z 匹配字符串结尾。 |
22 | \G 上一场比赛结束的比赛点。 |
23 | \b 匹配括号外的单词边界。在括号内时匹配退格键 (0x08)。 |
24 | \B 匹配非单词边界。 |
25 | \n、\t 等 匹配换行符、回车符、制表符等。 |
26 | \1...\9 匹配第 n 个分组子表达式。 |
27 | \10 如果已匹配,则匹配第 n 个分组子表达式。否则指字符代码的八进制表示形式。 |
28 | [艾欧] 匹配给定集合中的单个字符 |
29 | [^aeiou] 匹配给定集合之外的单个字符 |
^ 元字符匹配字符串的开头,$ 元符号匹配字符串的结尾。以下是一些简短的示例。
# nothing in the string (start and end are adjacent) /^$/ # a three digits, each followed by a whitespace # character (eg "3 4 5 ") /(\d\s) {3}/ # matches a string in which every # odd-numbered letter is a (eg "abacadaf") /(a.)+/ # string starts with one or more digits /^\d+/ # string that ends with one or more digits /\d+$/
让我们看另一个例子。
#!/usr/bin/perl $string = "Cats go Catatonic\nWhen given Catnip"; ($start) = ($string =~ /\A(.*?) /); @lines = $string =~ /^(.*?) /gm; print "First word: $start\n","Line starts: @lines\n";
当执行上面的程序时,它会产生以下结果 -
First word: Cats Line starts: Cats When
匹配边界
\ b匹配任何单词边界,由 \w 类和 \W 类之间的差异定义。因为 \w 包含单词的字符,而 \W 则相反,因此这通常意味着单词的终止。\B断言匹配任何不是字边界的位置。例如 -
/\bcat\b/ # Matches 'the cat sat' but not 'cat on the mat' /\Bcat\B/ # Matches 'verification' but not 'the cat on the mat' /\bcat\B/ # Matches 'catatonic' but not 'polecat' /\Bcat\b/ # Matches 'polecat' but not 'catatonic'
选择替代方案
| 的 | 字符就像 Perl 中的标准或按位 OR。它指定正则表达式或组中的备用匹配项。例如,要匹配表达式中的“cat”或“dog”,您可以使用以下命令 -
if ($string =~ /cat|dog/)
您可以将表达式的各个元素组合在一起以支持复杂的匹配。搜索两个人的名字可以通过两个单独的测试来实现,如下所示 -
if (($string =~ /Martin Brown/) || ($string =~ /Sharon Brown/)) This could be written as follows if ($string =~ /(Martin|Sharon) Brown/)
分组匹配
从正则表达式的角度来看,两者没有区别,只是前者可能稍微清晰一些。
$string =~ /(\S+)\s+(\S+)/; and $string =~ /\S+\s+\S+/;
然而,分组的好处是它允许我们从正则表达式中提取序列。分组按照它们在原始中出现的顺序作为列表返回。例如,在下面的片段中,我们从字符串中取出了小时、分钟和秒。
my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
除了这种直接方法之外,匹配组也可以在特殊的 $x 变量中使用,其中 x 是正则表达式中组的编号。因此,我们可以将前面的示例重写如下 -
#!/usr/bin/perl $time = "12:05:30"; $time =~ m/(\d+):(\d+):(\d+)/; my ($hours, $minutes, $seconds) = ($1, $2, $3); print "Hours : $hours, Minutes: $minutes, Second: $seconds\n";
当执行上面的程序时,它会产生以下结果 -
Hours : 12, Minutes: 05, Second: 30
当在替换表达式中使用组时,可以在替换文本中使用 $x 语法。因此,我们可以使用这个重新格式化日期字符串 -
#!/usr/bin/perl $date = '03/26/1999'; $date =~ s#(\d+)/(\d+)/(\d+)#$3/$1/$2#; print "$date\n";
当执行上面的程序时,它会产生以下结果 -
1999/03/26
\G 断言
\G 断言允许您从上次匹配发生的位置继续搜索。例如,在下面的代码中,我们使用 \G 以便我们可以搜索到正确的位置,然后提取一些信息,而无需创建更复杂的单个正则表达式 -
#!/usr/bin/perl $string = "The time is: 12:31:02 on 4/12/00"; $string =~ /:\s+/g; ($time) = ($string =~ /\G(\d+:\d+:\d+)/); $string =~ /.+\s+/g; ($date) = ($string =~ m{\G(\d+/\d+/\d+)}); print "Time: $time, Date: $date\n";
当执行上面的程序时,它会产生以下结果 -
Time: 12:31:02, Date: 4/12/00
\G 断言实际上只是 pos 函数的元符号等价物,因此在正则表达式调用之间您可以继续使用 pos,甚至通过使用 pos 作为左值子例程来修改 pos 的值(因此 \G)。
正则表达式示例
文字字符
先生。 | 示例和描述 |
---|---|
1 | 珀尔 匹配“Perl”。 |
字符类
先生。 | 示例和描述 |
---|---|
1 | [Pp]ython 匹配“Python”或“python” |
2 | 擦[耶] 匹配“ruby”或“rube” |
3 | [艾欧] 匹配任意一个小写元音 |
4 | [0-9] 匹配任意数字;与[0123456789]相同 |
5 | [阿兹] 匹配任何小写 ASCII 字母 |
6 | [AZ] 匹配任何大写 ASCII 字母 |
7 | [a-zA-Z0-9] 匹配以上任意一项 |
8 | [^aeiou] 匹配小写元音以外的任何内容 |
9 | [^0-9] 匹配数字以外的任何内容 |
特殊字符类
先生。 | 示例和描述 |
---|---|
1 | 。 匹配除换行符之外的任何字符 |
2 | \d 匹配数字:[0-9] |
3 | \D 匹配非数字:[^0-9] |
4 | \s 匹配空白字符:[ \t\r\n\f] |
5 | \S 匹配非空白:[^ \t\r\n\f] |
6 | \w 匹配单个单词字符:[A-Za-z0-9_] |
7 | \W 匹配非单词字符:[^A-Za-z0-9_] |
重复案例
先生。 | 示例和描述 |
---|---|
1 | Ruby? 匹配“rub”或“ruby”:y 是可选的 |
2 | Ruby* 匹配“rub”加上 0 个或多个 ys |
3 | Ruby+ 匹配“rub”加上 1 个或多个 ys |
4 | \d{3} 精确匹配 3 位数字 |
5 | \d{3,} 匹配 3 个或更多数字 |
6. | \d{3,5} 匹配 3、4 或 5 位数字 |
非贪婪重复
这匹配最小的重复次数 -
先生。 | 示例和描述 |
---|---|
1 | <.*> 贪婪重复:匹配“<python>perl>” |
2 | <.*?> 非贪婪:匹配“<python>perl>”中的“<python>” |
用括号分组
先生。 | 示例和描述 |
---|---|
1 | \D\d+ 无组: + 重复 \d |
2 | (\D\d)+ 分组: + 重复 \D\d 对 |
3 | ([Pp]ython(, )?)+ 匹配“Python”、“Python、python、python”等。 |
反向引用
这再次匹配之前匹配的组 -
先生。 | 示例和描述 |
---|---|
1 | ([Pp])ython&\1ails 匹配 python&Pails 或 Python&Pails |
2 | (['"])[^\1]*\1 单引号或双引号字符串。\1 匹配第一组匹配的任何内容。\2 匹配第二组匹配的任何内容,等等。 |
备择方案
先生。 | 示例和描述 |
---|---|
1 | 蟒蛇|perl 匹配“python”或“perl” |
2 | 摩擦(y|le)) 匹配“Ruby”或“卢布” |
3 | Python(!+|\?) “Python”后面跟一个或多个!或者一个? |
锚
这就需要指定匹配位置。
先生。 | 示例和描述 |
---|---|
1 | ^Python 匹配字符串或内部行开头的“Python” |
2 | Python$ 匹配字符串或行末尾的“Python” |
3 | \APython 匹配字符串开头的“Python” |
4 | Python\Z 匹配字符串末尾的“Python” |
5 | \bPython\b 在单词边界处匹配“Python” |
6 | \brub\B \B 是非单词边界:匹配“rube”和“ruby”中的“rub”,但不单独匹配 |
7 | Python(?=!) 匹配“Python”,如果后跟感叹号 |
8 | Python(?!!) 匹配“Python”,如果后面没有感叹号 |
带括号的特殊语法
先生。 | 示例和描述 |
---|---|
1 | R(?#评论) 匹配“R”。剩下的都是评论 |
2 | R(?i)u 比 匹配“uby”时不区分大小写 |
3 | R(?i:uby) 与上面相同 |
4 | 擦(?:y|le)) 仅分组而不创建 \1 反向引用 |