我有一系列单词,如下所示
476pe
e586
9999
rrr
ABCF
Run Code Online (Sandbox Code Playgroud)
我必须编写一个正则表达式来匹配数字和带有字母的数字。从上面的字符串中我必须只匹配
476pe
e586
9999
Run Code Online (Sandbox Code Playgroud)
我尝试编写一个正则表达式,如下所示
^[\D]*[0-9]+[\D]*$
Run Code Online (Sandbox Code Playgroud)
但它不起作用。我使用在线正则表达式工具http://rubular.com/r/HQE2vG0pbu尝试了此操作,它显示整个字符串匹配。
由于其他答案已经给出了很多解决您问题的方法,让我尝试解释您所目睹的行为。
首先,Rubular特定于 Ruby 的正则表达式语义。(我没有关于 Ruby 和 Python 的 RegEx 引擎之间有何不同的确切信息)。由于您已标记python,您可能需要使用regex101或debuggex。我将使用这两个来解释。
现在,让我们在此处查看实际的正则表达式和数据。你的输入字符串是这样的
476dn
e586
9999
rrr
ABCF
Run Code Online (Sandbox Code Playgroud)
正则表达式可以通过两种方式查看输入。包含换行符的长字符串或由换行符分隔的字符串列表。我们可以使用 RegEx 标志来控制此行为,该标志称为多行标志(在 Python 中是re.MULTILINE或re.M)。引用Python文档,
重新M
重新多线
指定后,模式字符
'^'在字符串的开头和每行的开头(紧跟在每个换行符之后)匹配;并且模式字符'$'匹配字符串末尾和每行末尾(紧邻每个换行符之前)。默认情况下,'^'仅在字符串的开头、'$'字符串的末尾以及字符串末尾的换行符(如果有)之前匹配。
例如,在我们的例子中,如果未启用此标志,则输入字符串将被视为包含换行符的长字符串,并将匹配第一行中^之前的位置,以及最后一行中之后的位置。4$F
当启用该标志时, 和^将$分别匹配第一个和最后一个字符之前和之后的相应位置。所以,他们可以匹配以下内容
^之前的位置是什么时候4,$之后的位置是什么时候n^之前的位置是什么时候4,$之后的位置是什么时候6^之前的位置是什么时候4,$之后的位置是什么时候9^之前的位置是什么时候4,$之后的位置是什么时候r^之前的位置是什么时候4,$之后的位置是什么时候f^之前的位置是什么时候e,$之后的位置是什么时候6^之前的位置是什么时候e,$之后的位置是什么时候9^之前的位置是什么时候e,$之后的位置是什么时候r^之前的位置是什么时候e,$之后的位置是什么时候f^之前的位置是什么时候9,$之后的位置是什么时候9^之前的位置是什么时候9,$之后的位置是什么时候r^之前的位置是什么时候9,$之后的位置是什么时候f^之前的位置是什么时候r,$之后的位置是什么时候r^之前的位置是什么时候r,$之后的位置是什么时候F^之前的位置是什么时候A,$之后的位置是什么时候F由于它可以匹配多个位置,因此我们必须显式指定 RegEx 引擎,当我们使用多行字符串时,我们必须分别匹配每一行。在Python中,我们可以使用re.findallto re.finditer. 在正则表达式世界中,它通常用标志g, 全局搜索 来表示。
有了这个基本的了解,让我们再次查看您的数据。我相信 rubular 默认情况下已经启用了这两个功能。我们可以使用捕获组清楚地看到匹配项,就像在这个演示中一样,使用正则表达式
^([\D]*[0-9]+[\D]*)$
Run Code Online (Sandbox Code Playgroud)
我们可以用Python找到匹配项,就像这样
regex = re.compile(r"^[\D]*[0-9]+[\D]*$", re.MULTILINE)
print regex.findall(data)
# ['476pe', 'e586', '9999\nrrr\nABCF']
Run Code Online (Sandbox Code Playgroud)
给定的模式与第一行和第二行匹配,它应该很简单。但第三场比赛一开始可能很难理解。当我们说 时^[\D]*,它意味着 0 个或多个非数字字符。因此,空字符串也可以与 匹配[\D]*。因此,在 的开头9999,[\D]*匹配前面的空字符串9999,然后[0-9]+匹配数字9999和字符串的其余部分,直到末尾将匹配[\D]*。它也匹配换行符,因为\D除了数字之外的任何内容。由于换行符不是数字,因此即使换行符也已匹配。
另请注意,\D也允许其他特殊字符。引用文档,
当
UNICODE未指定标志时,匹配任何非数字字符;这相当于集合[^0-9]. 使用UNICODE,它将匹配除 Unicode 字符属性数据库中标记为数字的字符以外的任何字符。
所以,你可能想要更明确,就像tobias_k 的回答一样
^[0-9a-zA-Z]*[0-9][0-9a-zA-Z]*$
Run Code Online (Sandbox Code Playgroud)
这可以在Python中使用,就像这样
regex = re.compile(r"^[0-9a-zA-Z]*[0-9][0-9a-zA-Z]*$", re.MULTILINE)
print regex.findall(data)
# ['476pe', 'e586', '9999']
Run Code Online (Sandbox Code Playgroud)
或者,如果您可以将字符串分成多个字符串,那么您可以这样做
regex = re.compile(r"^[0-9a-zA-Z]*[0-9][0-9a-zA-Z]*$")
print [item for item in data.split() if regex.match(item)]
# ['476pe', 'e586', '9999']
Run Code Online (Sandbox Code Playgroud)