【问题标题】:Understanding the 're.search()' behavior in Python了解 Python 中的“re.search()”行为
【发布时间】:2015-03-30 18:05:55
【问题描述】:

这是我用来从字母数字字符串中拆分字母和数字的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]*"

我错过了什么吗?

【问题讨论】:

  • 您需要使用re.findall 函数,因为re.search 只会返回第一个匹配项。
  • 你为什么不在你的模式中使用原始字符串呢?喜欢r'[a-z]*'

标签: python regex python-2.7


【解决方案1】:

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

我刚刚也检查了 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
$ 

【讨论】:

  • 使用-o 开关grepecho "abcdefghijklmnopqrstuvwxyz1234567890" | grep -o "[0-9]*"。它只会打印匹配的文本,而不是整行。顺便说一句,我有GNU grep
  • @heemayl,我得到与 python、ruby 和 perl 相同的结果:echo "abc123" | grep -o "[a-z]*" 产生 abcecho "abc123" | grep -o "[0-9]*" 没有输出,echo "abc123" | grep -o "[0-9]*$" 产生 123跨度>
【解决方案2】:

我建议你使用re.findall 函数(为了进行全局匹配)而不是re.search,因为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,它将返回一个空字符串。这种行为是因为re.search 函数,它在找到第一个匹配项后停止。这里8 与上面的正则表达式不匹配,所以正如我所说,[a-z]* 正则表达式将匹配8 之前存在的空字符串。

正则表达式 = [0-9]*, 字符串 = "abcdefghijklmnopqrstuvwxyz1234567890"

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

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

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

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

>>> 

【讨论】:

  • 他的输入字符串只有一个匹配,为什么他需要findall
  • 他只需要在第一种情况下使用 re.findall。但是对于这两种情况,他都需要将* 更改为+
  • 你应该更清楚地解释它匹配input_string开头的空数字序列。
  • @AvinashRaj 我认为他不需要re.findall。通过+re.search,他得到了预期的结果。
  • @user5061 如果他想使用单个正则表达式同时获得字母和数字的输出,那么他需要使用re.findall 函数。
猜你喜欢
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多