Python 正则表达式 : match a range of numbers with a separator

标签 python regex

我希望用户输入一系列要打印的数字: 例如:

27-84

我想出了以下正则表达式:

^(?P<Begin>\d+)((-?)(?P<end>\d+)?)$

因此它将匹配:27-84 作为以下组:

Begin   [0-2]   `27`
2.  [2-5]   `-84`
3.  [2-3]   `-`
end [3-5]   `84`

看起来不错,但我想听听是否有更优雅的方法,或者是否有我正在监督的空腔。

说明:

  • 允许使用单个数字,例如:27
  • 单个数字以27-,应理解为27 to end
  • -10的单个数字,应理解为begin to 10
  • 具有 10-27 的序列应理解为 10 到 27(含)。

最佳答案

(下面是原始答案)

好的,随着你的澄清更新,你将无法使用正则表达式轻松地做到这一点那个,除非你也只接受一个-作为“从头开始结束”。在这种情况下,你可以使用这个:

>>> r = re.compile('^((?P<fixed>\d+)|(?P<begin>\d+)?-(?P<end>\d+)?)$')
>>> r.match('123').groupdict()
{'begin': None, 'fixed': '123', 'end': None}
>>> r.match('123-').groupdict()
{'begin': '123', 'fixed': None, 'end': None}
>>> r.match('-456').groupdict()
{'begin': None, 'fixed': None, 'end': '456'}
>>> r.match('-').groupdict()
{'begin': None, 'fixed': None, 'end': None}
>>> r.match('123-456').groupdict()
{'begin': '123', 'fixed': None, 'end': '456'}

否则,您将不得不使用更明确的案例:

>>> r = re.compile('^((?P<fixed>\d+)|-(?P<endonly>\d+)|(?P<begin>\d+)(?:-(?P<end>\d+)?))$')
>>> r.match('123').groupdict()
{'endonly': None, 'begin': None, 'fixed': '123', 'end': None}
>>> r.match('123-').groupdict()
{'endonly': None, 'begin': '123', 'fixed': None, 'end': None}
>>> r.match('-456').groupdict()
{'endonly': '456', 'begin': None, 'fixed': None, 'end': None}
>>> r.match('123-456').groupdict()
{'endonly': None, 'begin': '123', 'fixed': None, 'end': '456'}
>>> r.match('-') is None
True

如您所见,随后正确解释结果所需的工作量会增加。

不过,我建议您为此放弃正则表达式,直接在 Python 中进行解析。例如像这样:

def parseRange (expr):
    if not expr or not re.match('^\d*-?\d*$', expr):
        raise ValueError('Not a correct range')

    # single number
    if '-' not in expr:
        return int(expr), int(expr)
    else:
        begin, end = expr.split('-')
        begin = float('-inf') if begin == '' else int(begin)
        end = float('inf') if end == '' else int(end)
        return begin, end

这样使用:

>>> parseRange('123')
(123, 123)
>>> parseRange('123-')
(123, inf)
>>> parseRange('-456')
(-inf, 456)
>>> parseRange('123-456')
(123, 456)

原始答案

你可以去掉一些捕获组来简化它:

^(?P<begin>\d+)-(?P<end>\d+)$

这也解决了 - 可能没有第二个数字的问题,并且理论上(实际上)开始和结束可以没有任何分隔。

如果你不总是想匹配一个范围但又想允许单个数字,你可以将范围部分放在非捕获组中。这样你就不会得到额外的组:

^(?P<begin>\d+)(?:-(?P<end>\d+))?$

最后,如果你也想接受 to 作为分隔符,你甚至可以这样做:

^(?P<begin>\d+)(?:(?:-|\s+to\s+)(?P<end>\d+))?$
>>> r = re.compile('^(?P<begin>\d+)(?:-(?P<end>\d+))?$')
>>> r.match('123').groupdict()
{'begin': '123', 'end': None}
>>> r.match('123-456').groupdict()
{'begin': '123', 'end': '456'}

>>> r = re.compile('^(?P<begin>\d+)(?:(?:-|\s+to\s+)(?P<end>\d+))?$')
>>> r.match('123-456').groupdict()
{'begin': '123', 'end': '456'}
>>> r.match('123 to 456').groupdict()
{'begin': '123', 'end': '456'}

关于Python 正则表达式 : match a range of numbers with a separator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21511831/

相关文章:

python - Pandas - 查找和替换以 '<' 开头的值

ruby - 在文本中捕获所有大写字母 "phrase"

jquery使用正则表达式查找id包含字符串的选择器

python - Matplotlib 随着时间的推移绘制旧点消失的点

java - 利用现有数据库的应用程序的 Web 框架?

python - 为什么这在 c 中有效但在 python 中无效 : (a = 5) == 5

regex - 替换 abcde[退格键][退格键] -> abc

python - 从 tensorflow 中的向量构造成对矩阵

Python:回答终端提示

python - 使用 python 正则表达式匹配文件名末尾的 "~"