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前缀。

请注意,如果整个表达式匹配,则整个match表达式(即=〜或!〜左侧的表达式以及match运算符)将返回true。因此,声明-

$true = ($foo =~ m/foo/);

如果$foo匹配正则表达式,则将$true设置为1;如果匹配失败,则将$true设置为0。在列表上下文中,匹配项返回所有分组表达式的内容。如,从时间字符串中提取小时,分钟和秒时,我们可以使用-

my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);

匹配修饰符

匹配运算符支持自己的一组修饰符。/g修饰符允许全局匹配。/i修饰符将使区分大小写不区分大小写。这是修饰符的完整列表

Sr.No.Modifier & Description
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 ///实际上只是match运算符的扩展,它使您可以用某些新文本替换匹配的文本。运算符的基本形式是-

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.Modifier & Description
1

i

使匹配区分大小写。

2

m

指定如果字符串包含换行符或回车符,则^和$运算符现在将匹配换行符边界,而不是字符串边界。

3

o

仅对表达式求值一次。

4

s

匹配换行符。

5

x

允许您在表达式中使用空格以保持清晰度。

6

g

用替换文本替换所有出现的找到的表达式。

7

e

像对待Perl语句一样判断替换项,并将其返回值用作替换文本。

转化运算符

转化与替代原理相似但不相同,但是与替代原理不同,转化不使用正则表达式搜索替代值。转化运算符是-

tr/SEARCHLIST/REPLACEMENTLIST/cds
y/SEARCHLIST/REPLACEMENTLIST/cds

该转换将REARCHACEMENTLIST中的所有出现的字符替换为SEARCHLIST中的所有出现的字符。如,使用"The cat sat on the mat"。

#/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.Modifier & Description
1

c

补充SEARCHLIST。

2

d

删除找到但未替换的字符。

3

s

挤压重复的替换字符。

#!/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.Pattern & Description
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\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,etc.

匹配换行符,回车符,制表符等。

26

\1 ...\9

匹配第n个分组的子表达式。

27

\10

如果已经匹配,则匹配第n个分组的子表达式。否则是指字符代码的八进制表示形式。

28

[aeiou]

匹配给定集合中的单个字符

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中的标准或按位或。它在正则表达式或组中指定备用匹配项。如,要在表达式中匹配" 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的值)。

正则表达式示例

文字匹配

Sr.No.示例 & Description
1

Perl

匹配" Perl"。

字符匹配

Sr.No.示例 & Description
1

[Pp] ython

匹配" Python"或" python"

2

rub [ye]

匹配" ruby​​"或" rube"

3

[aeiou]

匹配任何一个小写的元音

4

[0-9]

匹配任何数字;与[0123456789]相同

5

[a-z]

匹配任何小写的ASCII字母

6

[A-Z]

匹配任何大写ASCII字母

7

[a-zA-Z0-9]

符合以上任何条件

8

[^ aeiou]

与小写元音匹配

9

[^ 0-9]

匹配数字以外的任何东西

特殊字符匹配

Sr.No.示例 & Description
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.示例 & Description
1

ruby?

匹配" rub"或" ruby​​":y是可选的

2

ruby*

匹配" rub"加上0或更多ys

3

ruby​​ +

匹配" rub"加上1个或多个y

4

\d {3}

精确匹配3位数字

5

\d {3,}

匹配3个或更多数字

6.

\d {3,5}

匹配3、4或5位数字

非贪婪重复匹配

这匹配最小的重复次数-

Sr.No.示例 & Description
1

<.*>

贪婪重复:匹配“ <python> perl>”

2

<.*?>

非贪婪:匹配“ <python> perl>”中的“ <python>”

用括号分组匹配

Sr.No.示例 & Description
1

\D\d +

无组:+重复\d

2

(\D\d)+

分组:+重复\D\d对

3

([Pp] ython(,)?)+

匹配" Python"," Python,python,python"等。

反向引用匹配

这再次匹配先前匹配的组-

Sr.No.示例 & Description
1

([Pp])ython&\1ails

Matches python&pails or Python&Pails

2

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

单引号或双引号字符串。\1匹配第一组匹配的任何内容。\2匹配第二组匹配的任何东西,依此类推。

备选匹配

Sr.No.示例 & Description
1

python | perl

匹配" python"或" perl"

2

rub(y | le))

匹配" ruby​​"或" ruble"

3

Python(!+ |\?)

" Python"后跟一个或多个!还是一个?

锚点匹配

这需要指定匹配位置。

Sr.No.示例 & Description
1

^ Python

在字符串或内部行的开头匹配" Python"

2

Python $

在字符串或行的末尾匹配" Python"

3

\APython

在字符串开头匹配" Python"

4

的Python\ž

匹配字符串末尾的" Python"

5

\bPython\b

在单词边界匹配" Python"

6

\brub\B

\B为非单词边界:匹配" rube"和" ruby​​"中的" rub",但不单独匹配

7

Python(?=!)

匹配" Python",如果后跟感叹号

8

Python(?!!)

匹配" Python",如果没有后跟感叹号

带括号的特殊匹配

Sr.No.示例 & Description
1

R(?#comment)

匹配" R"。所有其余的都是评论

2

R(?i)uby

匹配" uby"时不区分大小写

3

R(?i:uby)

同上

4

rub(?:y | le))

仅在不创建\1反向引用的情况下进行分组

点我分享笔记