Perl - 正则表达式

正则表达式是一串字符,用于定义您正在查看的图案. Perl中正则表达式的语法与您在其他正则表达式支持程序中的语法非常相似,例如 sed grep awk .

应用正则表达式的基本方法是使用模式绑定运算符=〜和〜.第一个运算符是测试和赋值运算符.

Perl中有三个正则表达式运算符.

  • 匹配正则表达式 -  m//

  • 替换正则表达式 -  s///

  • Transliterate Regular Expression  -  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的工作方式相同//运算符series.you可以使用自然匹配字符的任意组合作为表达式的分隔符.例如,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/);

将$ true设置为1,如果匹配失败,则设置为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: 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是我们正在寻找的文本的正则表达式. REPLACEMENT是我们要用来替换找到的文本的文本或正则表达式的规范.例如,我们可以使用以下正则表达式&minus替换所有出现的 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

压缩重复替换的字符.

修饰符删除与SEARCHLIST匹配的字符在REPLACEMENTLIST中没有相应的条目.例如 :

#!/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

+

匹配前面一个或多个表达式.

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

匹配空格.相当于[\\\\\\\\].

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

[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

匹配边界

匹配任何单词边界,由\w class和\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语法可用于替换文本.因此,我们可以使用此&minus重新格式化日期字符串;

#!/usr/bin/perl

$date = '03/26/1999';
$date =~ s#(\d+)/(\d+)/(\d+)#$3/$1/$2#;

print "$date\n";

当执行上述程序时,它会产生以下结果 :

1999/03/26

\G Assertion

\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";

当执行上述程序时,它会产生以下结果 :

1999/03/26

\G断言实际上只是pos函数的metasymbol等价物,所以在正则表达式调用之间你可以继续使用pos,甚至可以通过使用pos作为左值子程序来修改pos的值(因此修改\ G).

正则表达式示例

文字字符

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]

\S

匹配非空白:[^ \t\r\n\f]

6

\ w

匹配单个字符:[A-Za-z0-9 _]


7

\ w

匹配一个非单词字符:[^ A-Za-z0-9 _]




Sr.No.Example & Description
1

ruby?

Matches "rub" or "ruby": the y is optional

2

ruby*

Matches "rub" plus 0 or more ys

3

ruby+

Matches "rub" plus 1 or more ys

4

\d{3}

Matches exactly 3 digits

5

\d{3,}

Matches 3 or more digits

6.

\d{3,5}

Matches 3, 4, or 5 digits

这匹配最小的重复次数 :
Sr.No.示例&说明
1

<.*>

贪婪重复:匹配"< python> perl>"

2

<.*?>

Nongreedy:匹配"< python>"在"< python> perl>"

使用括号分组

Sr.No.示例&说明
1

\D\d+

没有组:+重复\d

2

(\D\d)+

分组:+重复\ D \ d对

3

([Pp] ython(,)?)+

匹配"Python" ,"Python,python,python"等.

反向引用

这匹配先前匹配的组 :

Sr.No.示例&说明
1

([Pp])ython& \1ails

匹配python&pails或Python& Pails

2

(['"])[^ \1] * \ n

单引号或双引号字符串.\ n匹配第一组匹配的任何内容.\\\匹配第二组匹配的任何内容.

替代品

Sr.No.示例&描述
1

python | perl

匹配"python"或"perl"

2

rub(y | le))

匹配"ruby"或"卢布"

3

Python(!+ | \?)

"Python"一个或多个!或者一个?

锚点

这需要指定匹配位置.

Sr.No.示例&说明
1

^Python

Matches "Python" at the start of a string or internal line

2

Python$

Matches "Python" at the end of a string or line

3

\APython

Matches "Python" at the start of a string

4

Python\Z

Matches "Python" at the end of a string

5

\bPython\b

Matches "Python" at a word boundary

6

\brub\B

\B is nonword boundary: match "rub" in "rube" and "ruby" but not alone

7

Python(? =!)

Matches "Python", if followed by an exclamation point

8

Python(?!!)

Matches "Python", if not followed by an exclamation point

带括号的特殊语法

Sr.No.Example & Description
1

R(?#comment)

Matches "R". All the rest is a comment

2

R(?i)uby

Case-insensitive while matching "uby"

3

R(?i:uby)

Same as above

4

rub(?:y|le))

Group only without creating \1 backreference