【问题标题】:How to match beginning of string or character in Python如何在Python中匹配字符串或字符的开头
【发布时间】:2012-08-26 01:42:02
【问题描述】:

我有一个由参数号_参数号组成的字符串:

dir = 'a1.8000_b1.0000_cc1.3000_al0.209_be0.209_c1.344_e0.999'

我需要获取所选参数后面的数字,即

  • par='be' -->需要0.209
  • par='e' -->需要0.999

我试过了:

num1 = float(re.findall(par + '(\d+\.\d*)', dir)[0])

但是对于par='e',这将匹配0.209 0.999,所以我尝试将参数与字符串的开头或下划线一起匹配:

num1 = float(re.findall('[^_]'+par+'(\d+\.\d*)', dir)[0])

由于某种原因无法正常工作。

有什么建议吗?谢谢!

【问题讨论】:

    标签: python regex findall


    【解决方案1】:

    您的[^_] 模式匹配任何不是下划线的字符

    改用(..|..)分组:

    float(re.findall('(?:^|_)' + par + r'(\d+\.\d*)', dir)[0])
    

    我在那里使用了(?:..) 非捕获组,这样它就不会干扰您的原始组索引。

    演示:

    >>> import re
    >>> dir = 'a1.8000_b1.0000_cc1.3000_al0.209_be0.209_c1.344_e0.999'
    >>> par = 'e'
    >>> re.findall('(?:^|_)' + par + r'(\d+\.\d*)', dir)
    ['0.999']
    >>> par = 'a'
    >>> re.findall('(?:^|_)' + par + r'(\d+\.\d*)', dir)
    ['1.8000']
    

    详细说明,当使用一个字符组 ([..]) 并且您使用插入符号 (^) 开始 该组时,您反转字符组,将其从匹配列出的字符变为改为匹配 其他所有内容

    >>> re.findall('[a]', 'abcd')
    ['a']
    >>> re.findall('[^a]', 'abcd')
    ['b', 'c', 'd']
    

    【讨论】:

    • 这行得通。谢谢!但是你能解释一下 ?: 到底是做什么的吗?
    • @user1638145:它让我们像普通括号一样分组,但内容不会被放入捕获组。另一方面,数字匹配组((\d.\d*)确实捕获,因此作为第一个值返回;您已经使用[0] 索引选择了它。例如,如果我没有使用 ?: 指示符,则每次匹配都会返回 2 个值:['_', '0.999'] 代表 'e',或 ['', '1.8000'] 代表 'a'
    • 我认为您需要在部分正则表达式前面添加一个“r”...r'(\d+\.\d*).
    • 太棒了!我们可以在非捕获括号的帮助下显式地指向字符串 另一个字符序列的开头。
    【解决方案2】:

    没有regex的解决方案:

    def func(par,strs):
        ind=strs.index('_'+par)+1+len(par)
        ind1=strs.find('_',ind) if strs.find('_',ind)!=-1 else len(strs)
        return strs[ind:ind1]
    

    输出:

    >>> func('be',dir)
    '0.209'
    >>> func('e',dir)
    '0.999'
    >>> func('cc',dir)
    '1.3000'
    

    【讨论】:

      【解决方案3】:

      没有正则表达式的解决方案:

      >>> def get_value(dir, parm):
      ...     return map(float, [t[len(parm):] for t in dir.split('_') if t.startswith(parm)])
      ... 
      >>> get_value('a1.8000_b1.0000_cc1.3000_al0.209_be0.209_c1.344_e0.999', "be")
      [0.20899999999999999]
      

      如果该参数在字符串中多次出现,则全部计算。

      还有一个不强制转换为浮点数的版本:

      return [t[len(parm):] for t in dir.split('_') if t.startswith(parm)]
      

      【讨论】:

      • 我会用 int 替换 float。 Float 在最后加上数字,这不是他所追求的确切结果。否则,这是一种非常pythonic的方式。
      • int 不是一个好主意,因为四舍五入会丢失信息。不过,我们可以跳过转换为数字的过程(我稍后会编辑答案)。
      【解决方案4】:
      (?P<param>[a-zA-Z]*)(?P<version>[^_]*)
      

      【讨论】:

        猜你喜欢
        • 2018-02-24
        • 2020-01-04
        • 1970-01-01
        • 1970-01-01
        • 2017-08-20
        • 1970-01-01
        • 2021-11-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多