我正在编写 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
上失败(这可能应该被解释为两个数字 1234
和 12
) 由于 123
与 COMMA_SEP_NUMBER 模式相匹配。
这是此技术的一个问题,因为如果 DECIMAL_NUMBER 模式最先出现,则永远不会匹配 COMMA_SEP_NUMBER。
最后,这是一个可视化正则表达式的好工具
\d{1,3}(?:,\d{3})*(?:\.(?:\d{3},)*\d{0,3})?
关于Python:使用正则表达式从字符串中解析数值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20876457/