Perl

单个查找替换效率低下,于是就想着是否有方便的工具,但是不想使用 $Python$,就考虑到 $Perl$,虽然 $Perl$ 相对来说古怪一些,但是在接触以后,发现它还是很强大的,而且充满了乐趣。以下作为学习 $Perl$ 中的 $RegEx$ 的一些记录。

什么是正则表达式

A regular expression, regex or regexp (sometimes called a rational expression)is a sequence of characters that define a search pattern. Usually such patterns are used by string searching algorithms for “find” or “find and replace” operations on strings, or for input validation. It is a technique developed in theoretical computer science and formal language theory.

以上是WiKipedia上的定义,也就是说正则表达式是一种特殊的字符序列,可以用来定义如何搜索匹配样本。

在 Perl 中,通常使用 / / 来界定匹配样本(实际上是 m//, m通常可以省略 )。

1
/ab/     # 表示匹配 ab 字符串

但是如果在匹配源中本身就存在 /字符时,整个匹配样本就显得难以区分。

1
/http:\/\//  # \字符用于转义 /字符

实际上Perl对 / / 并不做硬性的要求,因此只要是使用成对的定界符即可,比如

1
m%http:\/\/% or m{http:\/\/}

这些都可以达到一样的效果。
如何对特定变量进行正则匹配呢?这时就需要使用捆绑操作符(the binding operator )=~ 。

1
2
3
4
my $one_url = "https://maxximues.github.io";
if($one_url =~ /^http:\/\//) {
print "这是一个URL\n";
}

^表示从头开始匹配

捷径—方便用于正则匹配中的”记号”

  • . —用于匹配任意单个字符,除新的一行以外。

    1
    /ab.a/ # 可以用于匹配 abaa,abba....
  • 重复词Quantifiers

Number to match Metacharacter Generalized form
Optional ? {0,1}
Zero or more * {0,}
One or more + {1,}
Minimum or more {min,}
Minimum with maximum {min,max}
Exactly {exactly_number}
1
2
3
4
5
/abb?a/ # 匹配 abba 或者 aba
/abb*a/ # 匹配 aba 或者 abba,abbba,abb...ba
/abb+a/ # 匹配 abba 或者 abbba,abbb...ba
/abb{2,3}a/ # 匹配 abbba,abbbba
/abb{4}a/ # 匹配 abbbbba

重复词只能将它最邻近字符重复匹配。

  • 分组Group

如何将特定字段重复匹配呢?使用 () 将需要可能重复的字段囊括起来。

1
2
/fred{1,2}/ # 匹配 fred,fredd
/(fred){1,2}/ # 匹配 fred 或者 fredfred

且根据括号使用的先后,可以使用\num,来代表这组匹配,num表示第几个出现的括号

1
2
3
4
5
use v5.10;
my $str = "Fred anda and Fred anda are my friends.";
if($str =~ /(Fred) (anda) and \1 \2/) {
print "Yes";
}

ekcNo4.png

当括号使用次数很多时,使用 \num 这种方式就很容易出错,所以在v5.10版本后,可以使用 \g{num} 来清楚指定第几个括号中的内容,且不容和匹配源中的文字产生歧义。

1
2
/(.)\111/ # 这时就会产生歧义,\1 \11 \111 这三个都可能是
/(.)\g{1}11/ # 这是就准确表示匹配 (.)(.)11
  • 可选词Alternatives

    1
    /fred|barney/
  • 字符类Character Classes

    1
    2
    3
    4
    /[a-z]/ # 表示一个小写字母 a-z 的匹配
    /[A-Z]/ # 表示一个大写字母 A-Z 的匹配
    /[0-9]/ # 表示一个数字 0-9 的匹配
    /[A-Z]+/ # 表示大写字母 A-Z 的匹配

事实上在使用时这些也有一些简便方法

1
2
3
4
/[0-9]/ == /\d/ # decimal digits
/[a-zA-Z]/ == /\D/ # not a decimal digit
/ / == /\s/ # whitespace
...
  • 定位开头末尾的”锚”Anchors
    1
    /^w{3}\.(\w)+@(\w)+\.com(\.cn)?$/ # ^表示字符串开头匹配,$表示字符串末尾匹配,整体匹配一个邮箱

eAsWCR.png
在Perl 5中,也可以使用 \A\Z来分别表示开头和末尾。