Python 为什么';这个正则表达式在所有情况下都能工作吗?

Python 为什么';这个正则表达式在所有情况下都能工作吗?,python,regex,Python,Regex,我有一个包含如下条目的文本文件: @markwarner VIRGINIA - Mark Warner @senatorleahy VERMONT - Patrick Leahy NO @senatorsanders VERMONT - Bernie Sanders @orrinhatch UTAH - Orrin Hatch NO @jimdemint SOUTH CAROLINA - Jim DeMint NO @senmikelee UTAH -- Mike Lee @kayb

我有一个包含如下条目的文本文件:

@markwarner VIRGINIA - Mark Warner 
@senatorleahy VERMONT - Patrick Leahy NO 
@senatorsanders VERMONT - Bernie Sanders 
@orrinhatch UTAH - Orrin Hatch NO 
@jimdemint SOUTH CAROLINA - Jim DeMint NO 
@senmikelee UTAH -- Mike Lee 
@kaybaileyhutch TEXAS - Kay Hutchison 
@johncornyn TEXAS - John Cornyn 
@senalexander TENNESSEE - Lamar Alexander
我编写了以下代码以使用正则表达式删除“否”和破折号:

import re

politicians = open('testfile.txt')
text = politicians.read()

# Grab the 'no' votes
# Should be 11 entries
regex = re.compile(r'(no\s@[\w+\d+\.]*\s\w+\s?\w+?\s?\W+\s\w+\s?\w+)', re.I)
no = regex.findall(text)

## Make the list a string
newlist = ' '.join(no)

## Replace the dashes in the string with a space
deldash = re.compile('\s-*\s')
a = deldash.sub(' ', newlist)

# Delete 'NO' in the string
delno = re.compile('NO\s')
b = delno.sub('', a)

# make the string into a list
# problem with @jimdemint SOUTH CAROLINA Jim DeMint
regex2 = re.compile(r'(@[\w\d\.]*\s[\w\d\.]*\s?[\w\d\.]\s?[\w\d\.]*?\s+?\w+)', re.I)
lst1 = regex2.findall(b)

for i in lst1:
    print i
当我运行代码时,它会捕获twitter句柄、州和全名,而不是Jim DeMint的姓氏。我已经声明我想忽略正则表达式的情况

有什么想法吗?为什么这个表达不包含这个姓氏

text=re.sub(' (NO|-+)(?= |$)','',text)
为了捕捉一切:

re.findall('(@\w+) ([A-Z ]+[A-Z]) (.+?(?= @|$))',text)
或者一下子:

re.findall('(@\w+) ([A-Z ]+[A-Z])(?: NO| -+)? (.+?(?= @|$))',text)
为了捕捉一切:

re.findall('(@\w+) ([A-Z ]+[A-Z]) (.+?(?= @|$))',text)
或者一下子:

re.findall('(@\w+) ([A-Z ]+[A-Z])(?: NO| -+)? (.+?(?= @|$))',text)

因为他的州名包含两个词:南卡罗来纳州

如果你的第二个正则表达式是这样,应该会有帮助

 (@[\w\d\.]*\s[\w\d\.]*\s?[\w\d\.]\s?[\w\d\.]*?\s+?\w+(?:\s\w+)?)
我补充说

(?:\s\w+)?
这是一个可选的非捕获组,与后跟一个或多个字母数字下划线字符的空格相匹配

显示它正确匹配带有编号和破折号的输入

编辑: 如果您希望一个主正则表达式捕获并正确拆分所有内容,请在删除Nos和破折号后,使用

((@[\w]+?\s)((?:(?:[\w]+?)\s){1,2})((?:[\w]+?\s){2}))
你可以在这里玩:

完全匹配的价格为1美元,Twitter句柄价格为2美元,状态价格为3美元,名称价格为4美元

每个捕获组的工作如下:

(@[\w]+?\s)
这匹配一个@符号,后跟至少一个但尽可能少的字符,直到空格

((?:(?:[\w]+?)\s){1,2})
这将匹配并捕获一个或两个单词,它们应该是状态。这只适用于下一篇文章,它必须有两个单词

((?:[\w]+?\s){2})

精确匹配并捕获两个单词,定义为尽可能少的字符,后跟空格,因为他的州名包含两个单词:SOUTH CAROLINA

如果你的第二个正则表达式是这样,应该会有帮助

 (@[\w\d\.]*\s[\w\d\.]*\s?[\w\d\.]\s?[\w\d\.]*?\s+?\w+(?:\s\w+)?)
我补充说

(?:\s\w+)?
这是一个可选的非捕获组,与后跟一个或多个字母数字下划线字符的空格相匹配

显示它正确匹配带有编号和破折号的输入

编辑: 如果您希望一个主正则表达式捕获并正确拆分所有内容,请在删除Nos和破折号后,使用

((@[\w]+?\s)((?:(?:[\w]+?)\s){1,2})((?:[\w]+?\s){2}))
你可以在这里玩:

完全匹配的价格为1美元,Twitter句柄价格为2美元,状态价格为3美元,名称价格为4美元

每个捕获组的工作如下:

(@[\w]+?\s)
这匹配一个@符号,后跟至少一个但尽可能少的字符,直到空格

((?:(?:[\w]+?)\s){1,2})
这将匹配并捕获一个或两个单词,它们应该是状态。这只适用于下一篇文章,它必须有两个单词

((?:[\w]+?\s){2})

匹配并捕获两个单词,定义为尽可能少的字符,后跟空格

这很好,但我不理解为什么可选的非捕获组捕获姓氏。它不应该使用组抓取文本而不是打印文本吗?另外,将非捕获组用于可能由两部分组成的状态名是否是一个更好的主意?也许,但这需要更多的工作。问题是您原来的正则表达式捕获了一个twitter句柄,后跟两三个单词。这一个捕获一个twitter句柄,后跟两个、三个或四个单词。这很有效,但我不明白为什么可选的非捕获组捕获姓氏。它不应该使用组抓取文本而不是打印文本吗?另外,将非捕获组用于可能由两部分组成的状态名是否是一个更好的主意?也许,但这需要更多的工作。问题是您原来的正则表达式捕获了一个twitter句柄,后跟两三个单词。这一个捕获了一个twitter句柄,后跟两个、三个或四个单词。这就是我要去的地方。regex是新手,所以这很有帮助。当我迭代并打印列表时,中间的一个似乎只返回字符串中的最后三个组。这就是我要去的地方。regex是新手,所以这很有帮助。当我迭代并打印列表时,中间的一个似乎只返回字符串中的最后三个组。