了解正则表达式中的组和或
Understanding group and or in regular expression
我正在寻找长字符串中的“一年”、“两年”、“2-3 年”或“3 - 4 年”等词。我尝试使用正则表达式来做到这一点。但是我不确定在涉及到组时我是否得到它。
让我们看看我的意思:
import re
text = 'one year, honey 2-5 year, dressed six, ten'
pattern = r'(one|two|three|four|five|six|seven|eight|nine|ten| \
eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen| \
eighteen|nineteen|twenty|[0-9]+[- ]*[0-9]*)[+ ]*year?'
re.findall(pattern, text) # ['one', '2-5']
我的问题是我想要['one year', '2-5 years']
。我不知道该怎么做。如果我忘记了单词中的数字:
pattern = r'[0-9]+[- ]*[0-9]*[\+ ]*year?'
re.findall(pattern, text) # ['2-5 years']
为什么我在第二个而不是第一个中得到 years
?我如何修改它以在第一个中获得年份?
提前致谢,
您需要先修正模式以匹配数字。这是一个例子:
>>> pattern = r'''(?x)\b(?:[0-9]+(?:[- ]*[0-9]+)?|one|two|three|four|five|six|seven|eight|nine|ten
|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)
[+ ]*years?\b'''
>>> re.findall(pattern, text)
['one year', '2-5 year']
参见Python demo and the regex demo。
详情
(?x)
- re.X
/ re.VERBOSE
内联修饰符
\b
- 单词边界
(?:
- 非捕获组的开始
[0-9]+(?:[- ]*[0-9]+)?
- 一个或多个数字后跟零个或多个空格或 -
然后一个或多个数字
|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty
- 交替列表中的单词之一
)
- 非捕获组结束
[+ ]*
- 零个或多个 +
或空格
years?
- year
或 years
\b
- 单词边界。
在您的正则表达式中,year?
应该是 years?
,因为它是可选的最后一个“s”,而不是“r”。您还需要使用所谓的 非捕获组 (?: ... )
来获取与整个正则表达式匹配的字符串;否则你只会得到括号中的子表达式匹配的字符串。
为了提高可读性,将长正则表达式划分为子表达式并赋予它们有意义的名称也是一个好主意。试试这个:
import re
text = 'one year, honey 2-5 year, dressed six, ten'
numberWordsRe = r'one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty'
numberOrIntervalRe=r'\d+(?:\s*-\s*\d+)'
pattern = r'\b(?:' + numberWordsRe + r'|' + numberOrIntervalRe + r')\s+years?\b'
print re.findall(pattern, text)
我正在寻找长字符串中的“一年”、“两年”、“2-3 年”或“3 - 4 年”等词。我尝试使用正则表达式来做到这一点。但是我不确定在涉及到组时我是否得到它。
让我们看看我的意思:
import re
text = 'one year, honey 2-5 year, dressed six, ten'
pattern = r'(one|two|three|four|five|six|seven|eight|nine|ten| \
eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen| \
eighteen|nineteen|twenty|[0-9]+[- ]*[0-9]*)[+ ]*year?'
re.findall(pattern, text) # ['one', '2-5']
我的问题是我想要['one year', '2-5 years']
。我不知道该怎么做。如果我忘记了单词中的数字:
pattern = r'[0-9]+[- ]*[0-9]*[\+ ]*year?'
re.findall(pattern, text) # ['2-5 years']
为什么我在第二个而不是第一个中得到 years
?我如何修改它以在第一个中获得年份?
提前致谢,
您需要先修正模式以匹配数字。这是一个例子:
>>> pattern = r'''(?x)\b(?:[0-9]+(?:[- ]*[0-9]+)?|one|two|three|four|five|six|seven|eight|nine|ten
|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)
[+ ]*years?\b'''
>>> re.findall(pattern, text)
['one year', '2-5 year']
参见Python demo and the regex demo。
详情
(?x)
-re.X
/re.VERBOSE
内联修饰符\b
- 单词边界(?:
- 非捕获组的开始[0-9]+(?:[- ]*[0-9]+)?
- 一个或多个数字后跟零个或多个空格或-
然后一个或多个数字|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty
- 交替列表中的单词之一
)
- 非捕获组结束[+ ]*
- 零个或多个+
或空格years?
-year
或years
\b
- 单词边界。
在您的正则表达式中,year?
应该是 years?
,因为它是可选的最后一个“s”,而不是“r”。您还需要使用所谓的 非捕获组 (?: ... )
来获取与整个正则表达式匹配的字符串;否则你只会得到括号中的子表达式匹配的字符串。
为了提高可读性,将长正则表达式划分为子表达式并赋予它们有意义的名称也是一个好主意。试试这个:
import re
text = 'one year, honey 2-5 year, dressed six, ten'
numberWordsRe = r'one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty'
numberOrIntervalRe=r'\d+(?:\s*-\s*\d+)'
pattern = r'\b(?:' + numberWordsRe + r'|' + numberOrIntervalRe + r')\s+years?\b'
print re.findall(pattern, text)