如何提取单词后出现的第一个浮点数?

How to extract first floating numbers appearing after a word?

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

我有这样的文字,

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.00\n.00\n.00\n.00\n.00\n.50\nSub Total\nTax\n8.50\n.94\nTotal\n1.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 应该匹配单词 total 并提取出现在它旁边的浮点数。

感谢任何帮助。

这是我试过的,

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

这样的事情可能会成功:

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

确保忽略大小写。

你可以试试

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

Demo

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

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)

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

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

部分:

  • (?<!\bsub ) 负向后视,断言左边不是单词 sub 和 space
  • \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.00\n.00\n.00\n.00\n.00\n.50\nSub Total\nTax\n8.50\n.94\nTotal\n1.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+ 白色 space 个字符:

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

Regex demo