Perl 正则表达式
-
正则表达式
正则表达式是一串字符串,用于定义您正在查看的一个或多个模式。Perl中正则表达式的语法与其他正则表达式支持程序(例如sed,grep和awk)非常相似。应用正则表达式的基本方法是使用模式绑定运算符=~和!~。第一个运算符是测试和赋值运算符。Perl 中有三个正则表达式运算符。- 匹配正则表达式-m//
- 替换正则表达式-s///
- 音译正则表达式-tr///
在每种情况下,正斜杠均用作您指定的正则表达式(regex)的定界符。如果您对其他定界符感到满意,则可以使用正斜杠代替。 -
匹配运算符
匹配运算符m//用于将字符串或语句与正则表达式匹配。例如,要将字符序列“foo”与标量$bar匹配,可以使用如下语句:
尝试一下$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><均有效。所以上面的例子可以重写如下:$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前缀。请注意,如果整个表达式匹配,则整个match表达式(即=~或!~左侧的表达式以及match运算符)将返回true(在标量上下文中)。因此,声明-$true = ($foo =~ m/foo/);
如果$foo匹配正则表达式,则将$true设置为1;如果匹配失败,则将$true设置为0。在列表上下文中,匹配项返回所有分组表达式的内容。例如,从时间字符串中提取小时,分钟和秒时,我们可以使用-my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
-
匹配运算符修饰符
匹配运算符支持自己的一组修饰符。/g修饰符允许全局匹配。/i修饰符将使区分大小写不区分大小写。这是修饰符的完整列表修饰符 说明 i 使区分大小写不敏感。 m 指定如果字符串具有换行符或回车符,则^和$运算符现在将匹配换行符边界,而不是字符串边界。 o 仅对表达式求值一次。 s 允许使用。 匹配换行符。 x 允许您在表达式中使用空格以保持清晰度。 g 全局查找所有匹配项。 cg 即使全局匹配失败,也允许继续搜索。 -
只匹配一次
匹配运算符还有一个更简单的版本-?PATTERN? 操作符。这与m//运算符基本相同,除了它在每个重置调用之间搜索的字符串内仅匹配一次。例如,您可以使用它来获取列表中的第一个和最后一个元素-
尝试一下@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
-
正则表达式变量
正则表达式变量包括$,它包含匹配的最后一个分组匹配的内容:$&,包含整个匹配的字符串:$`,包含匹配字符串之前的所有内容:$',其中包含匹配字符串之后的所有内容。以下代码演示了结果-
尝试一下$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///实际上只是match运算符的扩展,它使您可以用某些新文本替换匹配的文本。运算符的基本形式是-s/PATTERN/REPLACEMENT/;
PATTERN是我们要查找的文本的正则表达式。REPLACEMENT是我们要用来替换找到的文本的文本或正则表达式的规范。例如,我们可以更换所有出现的狗与猫使用下面的正则表达式-
尝试一下$string = "The cat sat on the mat"; $string =~ s/cat/dog/; print "$string\n";
当执行上述程序时,将产生以下结果-The dog sat on the mat
-
替换运算符修饰符
这是与替换运算符一起使用的所有修饰符的列表。修饰符 说明 i 使区分大小写不敏感。 m 指定如果字符串具有换行符或回车符,则^和$运算符现在将匹配换行符边界,而不是字符串边界。 o 仅对表达式求值一次。 s 允许使用。 匹配换行符。 x 允许您在表达式中使用空格以保持清晰度。 g 用替换文本替换所有出现的找到的表达式。 e 像对待Perl语句一样评估替换项,并将其返回值用作替换文本。 -
转换运算符
转换与替代原理相似但不相同,但是与替代原理不同,翻译(或音译)不使用正则表达式搜索替代值。翻译运算符是-tr/SEARCHLIST/REPLACEMENTLIST/cds y/SEARCHLIST/REPLACEMENTLIST/cds
该转换将REARCHACEMENTLIST中的所有出现的字符替换为SEARCHLIST中的所有出现的字符。例如,使用“The cat sat on the mat”。我们在本章中一直使用的字符串-
尝试一下$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/;
-
转换运算符修饰符
以下是与转换相关的运算符列表。修饰符 说明 c 补充SEARCHLIST。 d 删除找到但未替换的字符。 s 挤压重复的替换字符。 /d修饰符删除与SEARCHLIST匹配的,在REPLACEMENTLIST中没有相应条目的字符。例如-
尝试一下$string = 'the cat sat on the mat.'; $string =~ tr/a-z/b/d; print "$string\n";
当执行上述程序时,将产生以下结果-b b b.
最后一个修饰符/s删除被替换的重复字符序列,因此-
尝试一下$string = 'food'; $string = 'food'; $string =~ tr/a-z/a-z/s; print "$string\n";
当执行上述程序时,将产生以下结果-fod
-
更复杂的正则表达式
您不仅需要匹配固定的字符串。实际上,通过使用更复杂的正则表达式,您几乎可以匹配任何您梦昧以求的东西。这是一个快速备忘单-下表列出了Python中可用的正则表达式语法。模式 说明 ^ 匹配行首。 $ 匹配行尾。 . 匹配除换行符以外的任何单个字符。使用m选项还可以使其与换行符匹配。 [...] 匹配括号中的任何单个字符。 [^...] 匹配任何不在方括号中的单个字符。 * 匹配0个或多个出现的前一个表达式。 + 匹配1个或多个出现的前一个表达式。 ? 匹配0或1个出现的前一个表达式。 { n} 精确匹配前一个表达式的n次出现。 { n,} 匹配n个或多个出现的前一个表达式。 { n, m} 至少匹配n个,最多匹配m个先前的表达式。 a| b 匹配a或b。 \w 匹配单词字符。 \W 匹配非单词字符。 \s 匹配空格。等效于[\t\n\r\f]。 \S 匹配非空格。 \d 匹配数字。相当于[0-9]。 \D 匹配非数字。 \A 匹配字符串的开头。 \Z 匹配字符串的结尾。如果存在换行符,则匹配换行符。 \z 匹配字符串的结尾。 \G 比赛点,最后一场比赛结束。 \b 在方括号外时匹配单词边界。放在方括号内时,匹配退格键(0x08)。 \B 匹配非单词边界。 \n, \t, etc. 匹配换行符,回车符,制表符等。 \1...\9 匹配第n个分组的子表达式。 \10 如果已经匹配,则匹配第n个分组的子表达式。否则是指字符代码的八进制表示形式。 [aeiou] 匹配给定集合中的单个字符。 [^aeiou] 匹配给定集合外的单个字符。 ^元字符匹配字符串的开头,$元符号匹配字符串的结尾。这里有一些简短的例子。# 字符串中没有任何内容(起点和终点相邻) /^$/ # 三个数字,每个数字后跟一个空格 # character (eg "3 4 5 ") /(\d\s) {3}/ # 匹配一个字符串,其中每个 # odd-numbered letter is a (eg "abacadaf") /(a.)+/ # 字符串以一个或多个数字开头 /^\d+/ # 以一个或多个数字结尾的字符串 /\d+$/
让我们看另一个例子。
尝试一下$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包含相反的字符,这通常意味着单词的终止。该\乙断言这不是一个单词边界的任意位置相匹配。例如-/\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中的标准或按位或。它在正则表达式或组中指定备用匹配项。例如,要在表达式中匹配“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+)/; 和 $string =~ /\S+\s+\S+/;
但是,分组的好处是它允许我们从正则表达式中提取序列。分组以列表在原始组中出现的顺序作为列表返回。例如,在以下片段中,我们从字符串中抽出了小时,分钟和秒。my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
除此直接方法外,还可以在特殊的$ x变量中使用匹配的组,其中x是正则表达式中组的编号。因此,我们可以将前面的示例重写如下:
尝试一下$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语法。因此,我们可以使用以下格式重新格式化日期字符串:
尝试一下$date = '03/26/1999'; $date =~ s#(\d+)/(\d+)/(\d+)#$3/$1/$2#; print "$date\n";
当执行上述程序时,将产生以下结果-1999/03/26
-
\G 断言
\G 断言允许您从最后一次匹配的位置继续搜索。例如,在下面的代码中,我们使用\G,以便我们可以搜索到正确的位置然后提取一些信息,而无需创建更复杂的单个正则表达式-
尝试一下$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的值)。 -
正则表达式示例
字符字面量范例 说明 Perl 匹配“Perl” 字符类范例 说明 [Pp]ython 匹配“Python”或“python” rub[ye] 匹配“ruby”或“rube” [aeiou] 匹配任何一个小写的元音 [0-9] 匹配任何数字; 与[0123456789]相同 [a-z] 匹配任何小写ASCII字母 [A-Z] 匹配任何大写ASCII字母 [a-zA-Z0-9] 符合以上任何条件 [^aeiou] 匹配小写元音以外的其他任何东西 [^0-9] 匹配数字以外的任何东西 特殊字符类范例 说明 . 匹配除换行符以外的任何字符 \d 匹配数字:[0-9] \D 匹配一个非数字:[^ 0-9] \s 匹配空白字符:[\ t \ r \ n \ f] \S 匹配非空格:[^ \ t \ r \ n \ f] \w 匹配一个单词字符:[A-Za-z0-9_] \W 匹配一个非单词字符:[^ A-Za-z0-9_] 重复案例范例 说明 ruby? 匹配“rub”或“ruby”:y是可选的 ruby* 匹配“rub”加上0或更多ys ruby+ 匹配“rub”加上1个或多个y \d{3} 精确匹配3位数字 \d{3,} 匹配3个或更多数字 \d{3,5} 匹配3、4或5位数字 非贪婪重复这匹配最小的重复次数-范例 说明 <.*&g;t 贪婪重复:匹配“<python> perl>” <.*?&g;t 非贪婪:匹配“<python> perl>”中的“<python>” 用括号分组范例 说明 \D\d+ 无组:+重复\d (\D\d)+ 分组:+重复\D\d ([Pp]ython(, )?)+ 匹配“Python”,“Python,python,python” 等。 反向引用这再次匹配先前匹配的组-范例 说明 ([Pp])ython&\1ails 匹配python&pails或Python&Pails (['"])[^\1]*\1 单引号或双引号字符串。 \1匹配第一组匹配的任何内容。 \2匹配第二组匹配的任何东西,依此类推。 备择方案范例 说明 python|perl 匹配“python”或“perl” rub(y|le)) 匹配“ruby”或“ruble” Python(!+|\?) “Python”后跟一个或多个! 还是一个? 锚点 - 这需要指定匹配位置。范例 说明 ^Python 在字符串或内部行的开头匹配“ Python” Python$ 在字符串或行的末尾匹配“ Python” \APython 在字符串开头匹配“ Python” Python\Z 匹配字符串末尾的“ Python” \bPython\b 在单词边界匹配“ Python” \brub\B 匹配\ B为非单词边界:匹配“ rube”和“ruby”中的“rub”,但不单独 Python(?=!) 匹配“Python”,如果后跟感叹号 Python(?!!) 匹配“Python”,如果没有后跟感叹号 带括号的特殊语法范例 说明 R(?#comment) 匹配“R”。 其余的都是评论 R(?i)uby 匹配“uby”时不区分大小写 R(?i:uby) 同上 rub(?:y|le)) 仅在不创建\1反向引用的情况下进行分组