Python,匹配数字的正则表达式,x,xxx,xxx,但不是xx,xx,x,

Python,匹配数字的正则表达式,x,xxx,xxx,但不是xx,xx,x,,python,regex,Python,Regex,第一次发帖,我已经潜伏了一段时间,对这里的社区很有帮助 因此,与Al Sweigart的“自动化无聊的东西”合作 做一个需要我构建一个正则表达式来查找标准数字格式的数字的练习。三位数,逗号,三位数,逗号等 所以希望能匹配1234和23322,1234567和12,而不是1,23,1或,1111,或任何其他愚蠢的东西 我有以下几点 import re testStr = '1,234,343' matches = [] numComma = re.compile(r'^(\d{1,3})*(,\

第一次发帖,我已经潜伏了一段时间,对这里的社区很有帮助

因此,与Al Sweigart的“自动化无聊的东西”合作

做一个需要我构建一个正则表达式来查找标准数字格式的数字的练习。三位数,逗号,三位数,逗号等

所以希望能匹配1234和23322,1234567和12,而不是1,23,1或,1111,或任何其他愚蠢的东西

我有以下几点

import re

testStr = '1,234,343'
matches = []
numComma = re.compile(r'^(\d{1,3})*(,\d{3})*$')

for group in numComma.findall(str(testStr)):
    Num = group
    print(str(Num) + '-')           #Printing here to test each loop
    matches.append(str(Num[0]))

#if len(matches) > 0:
#    print(''.join(matches))
哪个输出这个

(‘1’、‘343’)-

我不知道为什么中间的“234”被跳过了。我敢肯定正则表达式有问题。只是我似乎不能把我的头放在这个上面

任何帮助或解释都将不胜感激

后续编辑。所以在遵循了你所有的建议,我可以吸收,我得到了它的工作完美的几个输入

import re

testStr = '1,234,343'
numComma = re.compile(r'^(?:\d{1,3})(?:,\d{3})*$')

Num = numComma.findall(testStr)
print(Num)
给我

['1234343']

太好了!但是当我将字符串输入更改为

“1234343和12345”

相同的代码返回

[]

Grrr。。。哈哈,我必须承认这很有趣

因此,本练习的目的是能够最终扫描一块文本,并以这种格式挑出所有数字。有什么见解吗?我想这会增加一个额外的元组,而不是返回一个空元组

后续编辑:

因此,一天后(忙于3个女儿和蜜糖清单),我终于能够坐下来检查我收到的所有帮助。以下是我的想法,它似乎完美无瑕。包括我个人理解的评论。再次感谢你所做的一切,布莱克特,萨利姆,姆霍克和布斯图斯

我的最终代码:

import re

testStr = '12,454 So hopefully will match 1,234 and 23,322 and 1,234,567 and 12 but not 1,23,1 or ,,1111, or anything else silly.'

numComma = re.compile(r'''
    (?:(?<=^)|(?<=\s))  # Looks behind the Match for start of line and whitespace
    ((?:\d{1,3})        # Matches on groups of 1-3 numbers.
    (?:,\d{3})*)        # Matches on groups of 3 numbers preceded by a comma
    (?=\s|$)''', re.VERBOSE)    # Looks ahead of match for end of line and whitespace

Num = numComma.findall(testStr)
print(Num)
重新导入
testStr='12454所以希望能匹配1234和23322以及1234567和12,但不能匹配1、23、1或、、1111或其他任何愚蠢的东西
numComma=re.compile(r''

(?:(?这个问题是因为您在模式中使用了一个重复捕获组,
(,\d{3})*
。Python的正则表达式引擎将与您的数字中的“千”和“一”组匹配,但只捕获最后一个重复

我怀疑您想改用非捕获组。在每组括号的开头添加
?:
(根据一般原则,我还建议使用原始字符串,尽管您当前的模式中没有转义问题):

由于未捕获任何组,
re.findall
将返回完整的匹配文本,我认为这是您想要的。您也可以使用
re.find
re.search
并对返回的
match
对象调用
group()

正则表达式匹配将为每个组返回一个元组项。但是,区分组和捕获是很重要的。因为您只有两个括号分隔的组,匹配将始终是两个元组:第一个组和第二个组。但是第二个组匹配两次

1
:第一组,已捕获
,234
:第二组,已捕获
,343
:也是第二组,这意味着它覆盖了
,234

不幸的是,除了最后一个组的捕获外,vanilla Python似乎没有类似于.NET的regex实现的方式来访问其他组的任何捕获。但是,如果您只想获取特定的数字,最好使用
re.search(数字)
。如果它返回一个非
None
值,则输入字符串是一个有效数字。否则,它不是

另外:在您的正则表达式上。请注意,正如Paul Hankin所述,测试用例6和7即使不应该匹配,但由于第一个捕获组后面的第一个*将使初始组匹配任意次数。否则,您的正则表达式是正确的

对编辑的响应:
现在正则表达式在“and”上返回一个空集的原因是正则表达式中的“^”和“$”锚点。正则表达式开头的“^锚点”表示“此点必须位于字符串的开头”。而$则是它的对应项,表示“此点必须位于字符串的结尾”。如果希望整个字符串从头到尾都是这样,这是很好的要匹配模式,但如果要选择多个数字,则应删除它们

然而!
如果将正则表达式保留为其当前的无锚形式,它现在将以单独的数字形式匹配1、23、45的各个元素。因此,我们需要添加一个零宽度的正向前瞻断言,并说“确保此数字后面是空白或行尾”。您可以看到更改。尾部,
(?=\s |$)
,这是我们的前瞻性断言:它不捕获任何内容,只是确保符合标准或条件,在本例中是空格(
\s
)或(
|
)行的结尾(
$

但是:类似地,前面的正则表达式会在“1234567”中匹配2,给我们数字“234567”,这将是不好的。因此,我们使用了一个类似于末尾的lookahead的lookback断言:
(?,仅当字符串开头或数字前有空格时才匹配。可以找到此版本,并且应完全满足任何与非十进制数字相关的需要。

尝试:

import re
p = re.compile(ur'(?:(?<=^)|(?<=\s))((?:\d{1,3})(?:,\d{3})*)(?=\s|$)', re.DOTALL)

test_str = """1,234 and 23,322 and 1,234,567 1,234,567,891 200 and 12 but
not 1,23,1 or ,,1111, or anything else silly"""

for m in re.findall(p, test_str):
    print m
重新导入

p=re.compile(ur’(?:(?此正则表达式将匹配任何有效数字,并且永远不会匹配无效数字:


(?为什么要使用findall?这不是问题,但您的regexp是错误的。第一个
*
是错误的,允许模式匹配非标准形式的内容:
'1234'
',123'
例如。我使用findall是因为我是一个完全的新手:)我会仔细阅读不同的方法,并遵循这里的建议。这是一个很好的解释,但建议的
import re
p = re.compile(ur'(?:(?<=^)|(?<=\s))((?:\d{1,3})(?:,\d{3})*)(?=\s|$)', re.DOTALL)

test_str = """1,234 and 23,322 and 1,234,567 1,234,567,891 200 and 12 but
not 1,23,1 or ,,1111, or anything else silly"""

for m in re.findall(p, test_str):
    print m