代码之家  ›  专栏  ›  技术社区  ›  heemayl

了解Python中的“re.search()”行为

  •  6
  • heemayl  · 技术社区  · 9 年前

    下面是我用来从一串字母数字中拆分字母和数字的python代码:

    input_string = 'abcdefghijklmnopqrstuvwxyz1234567890'
    import re
    print re.search('[a-z]*', input_string).group()
    print re.search('[0-9]*', input_string).group()
    

    在输出中,我得到的是字母串,而不是数字串。如果我修改如下代码,输出将显示数字:

    print re.search('[0-9]*$', input_string).group()
    

    我习惯了 grep 我发现它的功能与 re 模块,如果我在shell中运行以下命令,我会得到所需的结果:

    echo "abcdefghijklmnopqrstuvwxyz1234567890" | grep "[0-9]*"
    

    我在这里遗漏了什么吗?

    2 回复  |  直到 9 年前
        1
  •  10
  •   Avinash Raj    9 年前

    我建议你使用 re.findall 功能( 为了进行全球比赛 )而不是 re.search 因为 重新搜索 将只返回第一场比赛。

    >>> input_string = 'abcdefghijklmnopqrstuvwxyz1234567890'
    >>> print re.findall(r'\d+|[a-z]+', input_string)
    ['abcdefghijklmnopqrstuvwxyz', '1234567890']
    

    也不要使用 [a-z]* ,它也将返回空字符串。 * 将重复上一个令牌零次或多次,其中 + 将重复先前的令牌一次或多次。

    >>> print re.search(r'\d+', input_string).group()
    1234567890
    >>> print re.search(r'[a-z]+', input_string).group()
    abcdefghijklmnopqrstuvwxyz
    

    为什么第一个在第二个失败的情况下工作?

    >>> print re.search('[a-z]*', input_string).group()
    abcdefghijklmnopqrstuvwxyz
    >>> print re.search('[0-9]*', input_string).group()
    
    >>>
    

    * 重复上一个标记零次或多次,即它将匹配每个不匹配字符之前存在的空字符串。第一 [a-z]* 回报 abcdefghijklmnopqrstuvwxyz 因为此子字符串位于开头。如果输入类似 8abcdefghijklmnopqrstuvwxyz ,它将返回一个空字符串。这种行为是因为 重新搜索 函数,在找到第一个匹配项后停止。在这里 8 与上面的正则表达式不匹配,所以正如我所说, [a-z]* 正则表达式将匹配在 8. .

    正则表达式= [0-9]* ,string=“abcdefghijklmnopqrstuvxyz1234567890”

    重新搜索 找到第一个匹配项后停止。在这里 a 与不匹配 [0-9] 但是 [0-9]* 匹配之前存在的空字符串 因为 * 将重复上一个令牌 或更多次。这就是为什么在第二种情况下得到一个空字符串作为输出。

    >>> print re.search('[0-9]*$', input_string).group()
    1234567890
    

    由于我们添加了行尾锚,它将在行尾搜索零位或更多位。如果最后没有找到数字,它将返回一个空字符串作为匹配。

    >>> print re.search('[0-9]*$', '12foo').group()
    
    >>> 
    
        2
  •  1
  •   7stud    9 年前

    在输出中,我得到了字符串,但没有得到 数字字符串。

    我也检查了ruby和perl,它们产生了相同的结果。

    这个 digit pattern 比赛:

    1. 第一个字符和第二个字符之间的零宽度点。
    2. 第二个字符和第三个字符之间的零宽度点。
    3. 字符串末尾的数字序列。

    然而,re.search()只返回第一个匹配项。

    小写字母 letter pattern 比赛:

    1. 字符串开头的字母序列。
    2. 1和2之间的零宽度点。
    3. 2和3之间的零宽度点。

    如果我在shell中运行以下命令,我会得到所需的结果:

    echo "abcdefghijklmnopqrstuvwxyz1234567890" | grep "[0-9]*"
    

    在bash shell中,我得到:

    $ echo "abcdefghijklmnopqrstuvwxyz1234567890" | grep "[0-9]*"
    abcdefghijk
    

    我用echo、grep和其他模式得到了类似的奇怪结果。

    对评论的回应:

    $ bash --version
    GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
    Copyright (C) 2007 Free Software Foundation, Inc.
    
    $ echo "abc123" | grep -o "[a-z]*"
    abc
    $ echo "abc123" | grep -o "[0-9]*"
    $ echo "abc123" | grep -o "[0-9]*$"
    123
    $