【问题标题】:How to extract first floating numbers appearing after a word?如何提取单词后出现的第一个浮点数?
【发布时间】:2019-12-26 14:25:54
【问题描述】:

我正在尝试构建一个用于文本提取用例的应用程序,但我无法从中提取准确的价格。

我有这样的文字,

string1 = 'Friscos #8603\n8100 E. Orchard Road\nGreenwood Village, Colorado 80111\n2013-11-02\nTable 00\nGuest\n1 Oysters 1/2 Shell #1\n1 Crab Cake\n1 Filet 1602 Bone In\n1 Ribeye 22oz Bone In\n1 Asparagus\n1 Potato Au Gratin\n$17.00\n$19.00\n$66.00\n$53.00\n$12.00\n$11.50\nSub Total\nTax\n$178.50\n$12.94\nTotal\n$191.44\n'
string2 = 'Berghotel\nGrosse Scheidegg\n3818 Grindelwald\nFamilie R. Müller\nRech. Nr. 4572\nBar\n30.07.2007/13:29:17\nTisch 7/01\nNM\n#ರ\n2xLatte Macchiato à 4.50 CHF\n1xGloki\nà 5.00 CHF\n1xSchweinschnitzel à 22.00 CHF\n1xChässpätzli à 18.50 CHF\n#ರ #ರ #1ರ\n5.00\n22.00\n18.50\nTotal:\nCHF\n54.50\nIncl. 7.6% MwSt\n54.50 CHF:\n3.85\nEntspricht in Euro 36.33 EUR\nEs bediente Sie: Ursula\nMwSt Nr. : 430 234\nTel.: 033 853 67 16\nFax.: 033 853 67 19\nE-mail: grossescheidegg@bluewin.ch\n'

我想使用正则表达式提取出现在单词 total 之后的 price,但我只能提取所有浮动数字。另请注意,有时您可能还会看到诸如sub total 之类的词,但我只需要出现在词total 之后的价格。有时在total之后也可能出现其他词。所以 Regex 应该匹配 word total 并提取出现在它旁边的浮点数。

感谢任何帮助。

这是我尝试过的,

re.findall("\d+\.\d+", string1) # this returns all floating numbers.

【问题讨论】:

  • Total\nTax\n$178.50\n$12.94\nTotal\n$191.44\nstring1?
  • 如果您看到第一个总计的 string1 不只是总计,它是“小计”?我只需要在 total just total 之后提取浮点数。

标签: python regex regex-lookarounds


【解决方案1】:

你可以试试

(?<=\\nTotal)\:?\D+([\d\.]+)

Demo

【讨论】:

  • 这很好,但我认为 OP 很快意识到他还需要 '$' 或 'CHF'.... ?
【解决方案2】:

你可以试试这个,应该适用于你提到的例子和其他限制

import re
result = re.search('Total\n\$(\d+.\d+)', string1)
result.group(1) # 191.44
result = re.search('Total\:\n.+\n(\d+.\d+)', string2)
result.group(1) # 54.50

编辑:如果你只想要一个表达式,你可以试试

result = re.search('\nTotal\:?(\n\D+)*\n\$?(\d+.\d+)', string)
re.group(2)

【讨论】:

    【解决方案3】:

    您可以使用正向后视来防止 subtotal 之前,使用单词边界来防止单词成为更大单词的一部分,并使用捕获组来捕获价格。

    (?<!\bsub )\btotal\b\D*(\d+(?:\.\d+))
    

    部分:

    • (?&lt;!\bsub )否定的lookbehind,断言左边不是sub和空格
    • \btotal\b 匹配单词边界之间的总数,以防止它成为更大单词的一部分
    • \D* 匹配任何非数字字符的 0+ 次
    • ( 捕获第 1 组
      • \d+(?:\.\d+) 匹配 1+ 个数字和可选的小数部分
    • )关闭群

    Regex demo | Python demo

    例如

    import re
    
    regex = r"(?<!\bsub )\btotal\b\D*(\d+(?:\.\d+))"
    string1 = 'Friscos #8603\n8100 E. Orchard Road\nGreenwood Village, Colorado 80111\n2013-11-02\nTable 00\nGuest\n1 Oysters 1/2 Shell #1\n1 Crab Cake\n1 Filet 1602 Bone In\n1 Ribeye 22oz Bone In\n1 Asparagus\n1 Potato Au Gratin\n$17.00\n$19.00\n$66.00\n$53.00\n$12.00\n$11.50\nSub Total\nTax\n$178.50\n$12.94\nTotal\n$191.44\n'
    string2 = 'Berghotel\nGrosse Scheidegg\n3818 Grindelwald\nFamilie R. Müller\nRech. Nr. 4572\nBar\n30.07.2007/13:29:17\nTisch 7/01\nNM\n#ರ\n2xLatte Macchiato à 4.50 CHF\n1xGloki\nà 5.00 CHF\n1xSchweinschnitzel à 22.00 CHF\n1xChässpätzli à 18.50 CHF\n#ರ #ರ #1ರ\n5.00\n22.00\n18.50\nTotal:\nCHF\n54.50\nIncl. 7.6% MwSt\n54.50 CHF:\n3.85\nEntspricht in Euro 36.33 EUR\nEs bediente Sie: Ursula\nMwSt Nr. : 430 234\nTel.: 033 853 67 16\nFax.: 033 853 67 19\nE-mail: grossescheidegg@bluewin.ch\n'
    
    print(re.findall(regex, string1, re.IGNORECASE))
    print(re.findall(regex, string2, re.IGNORECASE))
    

    输出

    ['191.44']
    ['54.50']
    

    如果价格前面应该是文本 CHF 的美元符号,您可以使用 alternation (?:\$|CHF)\s* 匹配值,然后匹配 0+ 个空格字符:

    (?<!\bsub )\btotal\b\D*(?:\$|CHF)\s*(\d+(?:\.\d+))
    

    Regex demo

    【讨论】:

      【解决方案4】:

      这样的事情可能会奏效:

      (?<!sub )total.*?(\d+.\d+)
      

      请务必忽略大小写。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-02
        • 2018-04-05
        • 1970-01-01
        • 1970-01-01
        • 2011-04-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多