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反向引用的情况下进行分组