正则表达式(Regular Expressions)
正则表达式是一串字符,用于定义您正在查看的图案。 Perl中正则表达式的语法与您在其他正则表达式支持程序(如sed , grep和awk的语法非常相似。
应用正则表达式的基本方法是使用模式绑定运算符=〜和! 〜。 第一个运算符是测试和赋值运算符。
Perl中有三个正则表达式运算符。
- 匹配正则表达式 - m //
- 替代正则表达式 - s ///
- 音译正则表达式 - tr ///
每种情况下的正斜杠都充当您指定的正则表达式(正则表达式)的分隔符。 如果您对任何其他分隔符感到满意,则可以使用代替正斜杠。
匹配运算符
匹配运算符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;如果匹配失败,则将0设置为0。 在列表上下文中,匹配返回任何分组表达式的内容。 例如,从时间字符串中提取小时,分钟和秒时,我们可以使用 -
my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
匹配运算符修饰符
匹配运算符支持自己的一组修饰符。 /g修饰符允许全局匹配。 /i修饰符将使匹配大小写不敏感。 这是修饰符的完整列表
Sr.No. | 修饰符和描述 |
---|---|
1 | i 使匹配大小写不敏感。 |
2 | m 指定如果字符串具有换行符或回车符,则^和$运算符现在将匹配换行符边界而不是字符串边界。 |
3 | o 仅对表达式求值一次。 |
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: food, 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是我们正在寻找的文本的正则表达式。 REPLACEMENT是我们要用来替换找到的文本的文本或正则表达式的规范。 例如,我们可以使用以下正则表达式将所有出现的dog替换为cat -
#/user/bin/perl
$string = "The cat sat on the mat";
$string =~ s/cat/dog/;
print "$string\n";
执行上述程序时,会产生以下结果 -
The dog sat on the mat
替换运算符修饰符
以下是替换运算符使用的所有修饰符的列表。
Sr.No. | 修饰符和描述 |
---|---|
1 | i 使匹配大小写不敏感。 |
2 | m 指定如果字符串具有换行符或回车符,则^和$运算符现在将匹配换行符边界而不是字符串边界。 |
3 | o 仅对表达式求值一次。 |
4 | s 允许使用。 匹配换行符。 |
5 | x 允许您在表达式中使用空格以便清晰。 |
6 | g 用替换文本替换所有出现的表达式。 |
7 | e 将替换计算为Perl语句,并将其返回值用作替换文本。 |
翻译运算符
翻译与替换原则类似,但不完全相同,但与替换不同,翻译(或音译)不使用正则表达式来搜索替换值。 翻译经营者是 -
tr/SEARCHLIST/REPLACEMENTLIST/cds
y/SEARCHLIST/REPLACEMENTLIST/cds
该翻译将SEARCHLIST中出现的所有字符替换为REPLACEMENTLIST中的相应字符。 例如,使用“猫坐在垫子上”。 我们在本章中使用过的字符串 -
#/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/;
翻译运算符修饰符
以下是与翻译相关的运算符列表。
Sr.No. | 修饰符和描述 |
---|---|
1 | c 补充SEARCHLIST。 |
2 | d 删除已找到但未替换的字符。 |
3 | s Squheshes重复替换的字符。 |
/d修饰符删除与REPARACEMENT列表中没有相应条目的SEARCHLIST匹配的字符。 例如 -
#!/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中可用的正则表达式语法。
Sr.No. | 模式和描述 |
---|---|
1 | ^ 匹配行首。 |
2 | $ 匹配行尾。 |
3 | . 匹配除换行符之外的任何单个字符。 使用m选项也可以匹配换行符。 |
4 | [...] 匹配括号中的任何单个字符。 |
5 | [^...] 匹配不在括号中的任何单个字符。 |
6 | * 匹配前面表达式的0次或更多次出现。 |
7 | + 匹配1个或多个前面的表达式。 |
8 | ? 匹配前面表达式的0或1次出现。 |
9 | { n} 准确匹配前面表达式的n个出现次数。 |
10 | { n,} 匹配前面表达式的n次或多次出现。 |
11 | { n, m} 匹配前面表达式的至少n次和最多m次出现。 |
12 | a| b 匹配a或b。 |
13 | \w 匹配单词字符。 |
14 | \W 匹配非单词字符。 |
15 | \s 匹配空白。 相当于[\ t\n\r\n]。 |
16 | \S 匹配非空白。 |
17 | \d 匹配数字。 相当于[0-9]。 |
18 | \D 匹配非数字。 |
19 | \A 匹配字符串的开头。 |
20 | \Z 匹配字符串的结尾。 如果存在换行符,则它在换行符之前匹配。 |
21 | \z 匹配字符串的结尾。 |
22 | \G 匹配指向上一场比赛结束的位置。 |
23 | \b 在括号外匹配单词边界。 在括号内匹配退格(0x08)。 |
24 | \B 匹配非字边界。 |
25 | \n, \t, etc. 匹配换行符,回车符,制表符等。 |
26 | \1...\9 匹配第n个分组子表达式。 |
27 | \10 如果已匹配,则匹配第n个分组子表达式。 否则指的是字符代码的八进制表示。 |
28 | [aeiou] 匹配给定集合中的单个字符 |
29 | [^aeiou] 匹配给定集合之外的单个字符 |
^元字符匹配字符串的开头,$ metasymbol匹配字符串的结尾。 以下是一些简短的例子。
# 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函数的metasymbol等价物,因此在正则表达式调用之间你可以继续使用pos,甚至可以通过使用pos作为左值子程序来修改pos的值(因此也可以修改\ G)。
Regular-expression Examples
文字字符
Sr.No. | 示例和说明 |
---|---|
1 | Perl 匹配“Perl”。 |
角色类
Sr.No. | 示例和说明 |
---|---|
1 | [Pp]ython 匹配“Python”或“python” |
2 | rub[ye] 匹配“ruby”或“rube” |
3 | [aeiou] 匹配任何一个小写元音 |
4 | [0-9] 匹配任何数字; 与[0123456789]相同 |
5 | [az] 匹配任何小写ASCII字母 |
6 | [AZ] 匹配任何大写的ASCII字母 |
7 | [a-zA-Z0-9] 匹配以上任何一项 |
8 | [^aeiou] 匹配除小写元音之外的任何内容 |
9 | [^0-9] 匹配除数字之外的任何内容 |
特殊字符类
Sr.No. | 示例和说明 |
---|---|
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_] |
重复案件
Sr.No. | 示例和说明 |
---|---|
1 | ruby? 匹配“rub”或“ruby”:y是可选的 |
2 | ruby* 匹配“擦”加0或更多ys |
3 | ruby+ 匹配“擦”加1或更多ys |
4 | \d{3} 正好匹配3位数 |
5 | \d{3,} 匹配3位或更多位数 |
6. | \d{3,5} 匹配3,4或5位数 |
Nongreedy Repetition
这匹配最小的重复次数 -
Sr.No. | 示例和说明 |
---|---|
1 | 《.*》 贪心重复:匹配“ perl>” |
2 | 《.*?》 Nongreedy:匹配“ perl>”中的“” |
用括号分组
Sr.No. | 示例和说明 |
---|---|
1 | \D\d+ 没有组:+重复\ d |
2 | (\D\d)+ 分组:+重复\ D\d对 |
3 | ([Pp]ython(, )?)+ 匹配“Python”,“Python,python,python”等。 |
Backreferences
这与之前匹配的组再次匹配 -
Sr.No. | 示例和说明 |
---|---|
1 | ([Pp])ython&\1ails 匹配python和pails或Python&Pails |
2 | (['"])[^\1]*\1 单引号或双引号。 \1匹配第一组匹配的任何内容。 \2匹配第二组匹配的任何内容等。 |
替代品(Alternatives)
Sr.No. | 示例和说明 |
---|---|
1 | python|perl 匹配“python”或“perl” |
2 | rub(y|le)) 匹配“红宝石”或“卢布” |
3 | Python(!+|\?) “Python”后跟一个或多个! 还是一个? |
Anchors
这需要指定匹配位置。
Sr.No. | 示例和说明 |
---|---|
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”,如果没有后跟感叹号 |
带括号的特殊语法
Sr.No. | 示例和说明 |
---|---|
1 | R(?#comment) 匹配“R”。 其余的都是评论 |
2 | R(?i)uby 匹配“uby”时不区分大小写 |
3 | R(?i:uby) 与上面相同 |
4 | rub(?:y|le)) 仅在不创建\ 1反向引用的情况下进行分组 |