Python:使用正则表达式从字符串中解析数值

标签 python regex

我正在编写 python 代码以使用正则表达式从字符串中解析不同类型的数字,但遇到了一个我不明白的恼人问题。

我的代码如下:

import re    

test_string = "Distributions $54.00 bob $26 and 0.30 5% ($0.23) 2,333,450"

num_values = re.findall(r"\(?\$?[0-9]+.?[0-9]*%?\)?|[0-9]+(?:,[0-9]+)*", test_string)

输出是:

['$54.00', '0.30', '5%', '($0.23)', '2,333', '450']

所以代码对除 '2,333,450' 字符串以外的所有内容都很好,因为某种原因它被分成两个元素。

烦人的是,当我颠倒正则表达式的顺序时:

num_values = re.findall(r"[0-9]+(?:,[0-9]+)*|\(?\$?[0-9]+.?[0-9]*%?\)?", test_string)

我得到这个输出:

['$54.00', '$26 ', '0', '30', '5', '($0.23)', '2,333,450']

所以我的“2,333,450”字符串输出正常,但我无法正确解析带有 % 符号或小数点的数字(除非它在括号中)。

如有任何见解,我们将不胜感激。

最佳答案

首先,我怀疑正则表达式第一部分中的句点应该用前导反斜杠转义(如果它打算匹配小数点),目前它匹配任何字符,这就是为什么你有一个包含空格 '$26'.

2,333 因此与正则表达式的第一部分匹配(, 与未转义的 . 匹配),这就是为什么它与该号码的 ,450 部分不匹配。

虽然您的(更正后的)正则表达式适用于您有限的样本数据,这可能已经足够好了,但对于一般用途来说它可能过于宽泛 - 例如它匹配 ($1267.3%。您可以建立一个更大的正则表达式来自更小的部分,但是这会很快变得丑陋:

import re

test_string = "Distributions $54.00 bob $26 and 0.30 5% ($0.23) 2,333,450"
test_string += " $12,354.00 43 43.12 1234,12 ($123,456.78"

COMMA_SEP_NUMBER = r'\d{1,3}(?:,\d{3})*' # require groups of 3
DECIMAL_NUMBER = r'\d+(?:\.\d*)?'
COMMA_SEP_DECIMAL = COMMA_SEP_NUMBER + r'(?:\.(?:\d{3},)*\d{0,3})?' # are commas used after the decimal point?

regex_items = []

regex_items.append('\$' + COMMA_SEP_DECIMAL)
regex_items.append('\$' + DECIMAL_NUMBER)
regex_items.append(COMMA_SEP_DECIMAL + '\%')
regex_items.append(DECIMAL_NUMBER + '\%')
regex_items.append(COMMA_SEP_DECIMAL)
regex_items.append(DECIMAL_NUMBER)

r = re.compile('|'.join(regex_items))

print r.findall(test_string)

请注意,这不考虑数字周围的括号,它在 1234,12 上失败(这可能应该被解释为两个数字 123412) 由于 123 与 COMMA_SEP_NUMBER 模式相匹配。

这是此技术的一个问题,因为如果 DECIMAL_NUMBER 模式最先出现,则永远不会匹配 COMMA_SEP_NUMBER。

最后,这是一个可视化正则表达式的好工具

\d{1,3}(?:,\d{3})*(?:\.(?:\d{3},)*\d{0,3})?

Regular expression visualization

Debuggex Demo

关于Python:使用正则表达式从字符串中解析数值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20876457/

相关文章:

python bisect.insort(列表,值)

python - 在 python : difference between two lists

python - 使用特定的 python 版本将 python 脚本作为 Upstart 服务运行

java - 正则表达式匹配如果模式位于句子的开头,句子的结尾被空格包围

php - 正则表达式 - 匹配第二组括号 ([]) 之间的所有内容

javascript - 使用此正则表达式,为什么它只捕获最后一个列表项

python - 按顺序将值添加到列 pandas python

python - 在列表中查找单调序列?

php - 用php替换一部分网址

javascript - 我想通过 javascript 过滤密码,但是当我使用该代码时,无论我输入什么密码,它都会弹出警报