ruby 正则表达式从数字字符串中提取数字

jutyujz0  于 12个月前  发布在  Ruby
关注(0)|答案(4)|浏览(111)

我想要一个正则表达式从至少有一个数字的字符串中提取第一个数字(假设。用于小数,用于分隔千位数)

examples  = ["I earned $100,000", "I earned $100000", "I earned $100000.05"]
desired_output =  ["100000", "100000", "100000.05"]

下面是我尝试的一个正则表达式:

regex = /((\d{1,3}(?:,\d{3})*)(?:\.(\d{0,2}))?)/

但是,对于字符串“I earned $100000”,它提取的是“100”,而不是“100000”。

regex.match("I earned $100000") #returns 100

如何修改这个正则表达式?

sdnqo3pr

sdnqo3pr1#

您应该首先匹配整个文本["100,000","100000","100000.5"],然后删除不需要的分隔符。模式:[\d\,\.]+
您的正则表达式模式只匹配100,因为您将000留在未捕获组中

8yoxcaq7

8yoxcaq72#

examples = ["I earned $100,000", "I earned $100000", "I earned $100000.05"]

代码

p examples.map { |string| /\$([\d,.]+)/.match(string)[1] }

输出

["100,000", "100000", "100000.05"]
chhqkbe1

chhqkbe13#

您可以附加单词边界以防止部分单词匹配,而是匹配1+数字,如果您不需要捕获组,则可以省略它们:

\b\d+(?:,\d{3})*(?:\.\d{0,2})?\b

Regex demo

qxsslcnc

qxsslcnc4#

提取美元值,然后进行转换

假设你总是使用美元,而不是其他货币,即使你有一个空字符串或多个设置货币值,下面的方法也会起作用。

examples = [
  "I earned $100,000", "I earned $100000",
  "I earned $100000.05", "", 
  "I earned $2.50, which is half of $5.00"
]

examples.map { _1.scan(/\$(\d[\d,.]+)\b/).first }
  .compact.flatten.map { _1.delete ?, }

#=> ["100000", "100000", "100000.05", "2.50"]

其工作原理是提取所有带有前导美元符号的值,然后操作匹配项。步骤包括:

  • 使用String#scan捕获以美元符号为前缀、后跟单词边界的所有数字(包括小数和逗号)。
  • 没有努力验证示例集中的边缘情况,例如显式nil值,格式不正确的值(如$1.00.2)或负值(如-$1.00($5.00))。
  • 此外,请注意,前导或尾随零不一定是错误; $00.00在某些用例中可能完全有效,因此前导零、填充、小数精度或其他超出您问题范围的内容都不会得到解决。你可以用一个更复杂的正则表达式来做很多这样的验证,但是我个人认为你应该事后验证你的结果,而不是试图在一个正则表达式中完成所有的验证,以降低认知负荷。YMMV.
  • 如果找到多个金额,则仅选择字符串中的第一个金额。
  • 从结果中删除所有nil值。
  • 展平压缩的结果数组。
  • 从展平的String值数组中删除逗号。

当然有更短的解决方案,解决方案将更明确地说明什么是或不是一个有效的美元数额,但扫描/\$(\d[\d,.]+)\b/只是在概念上对我来说似乎更简单。这允许您将格式化和验证的问题从核心regexp中移除。
是使用链式方法处理结果集,还是对结果调用一系列“清理步骤”,这取决于您。恕我直言,你在正则表达式中做的工作越少,调试任何后续的转换或验证就越容易,这对你来说很重要。

相关问题