如何在ruby中混合连续的gsubs

时间:2011-08-09 17:59:29

标签: ruby regex gsub

我有以下

address.gsub(/^\d*/, "").gsub(/\d*-?\d*$/, "").gsub(/\# ?\d*/,"")

这可以在一个gsub中完成吗?我想传递一个模式列表而不是一个模式 - 它们都被同一个东西所取代。

3 个答案:

答案 0 :(得分:4)

您可以将它们与交替运算符(|)结合使用:

address = '6 66-666 #99 11-23'
address.gsub(/^\d*|\d*-?\d*$|\# ?\d*/, "")
# " 66-666  "

address = 'pancakes 6 66-666 # pancakes #99 11-23'
address.gsub(/^\d*|\d*-?\d*$|\# ?\d*/,"")
# "pancakes 6 66-666 pancakes  "

您可能希望添加更多的空白清理。你可能想切换到以下之一:

/\A\d*|\d*-?\d*\z|\# ?\d*/
/\A\d*|\d*-?\d*\Z|\# ?\d*/

取决于您的数据真实情况以及您需要如何处理换行符。

答案 1 :(得分:3)

结合正则表达式是一个好主意 - 而且相对简单 - 但我想建议一些额外的更改。即:

address.gsub(/^\d+|\d+(?:-\d+)?$|\# *\d+/, "")

在原始正则表达式中,^\d*\d*-?\d*$ 始终匹配,因为它们不必使用任何字符。因此,您可以保证在每一行上执行两次替换,即使这只是用空字符串替换空字符串。在我的正则表达式中,^\d+无需匹配,除非行的开头至少有一个数字,并且\d+(?:-\d+)?$匹配在结尾处看起来像整数或范围表达式的数字。线。

您的第三个正则表达式\# ?\d*将匹配任何#个字符,如果#后面跟一个空格和一些数字,那么它也将采用这些字符。根据您的其他正则表达式和我对其他问题的经验判断,我怀疑您只有在{{1>}后才会匹配一个或更多数字,并且可选空格介入。这就是我的第三个正则表达式。

如果我的任何猜测都是错误的,请说明你想要做什么,我会尽力提出正确的正则表达式。但我真的不认为前两个正则表达式至少是你想要的。


编辑(回答评论):在使用正则表达式时,您应该始终了解正则表达式匹配任何内容和正则表达式之间的区别< em>不匹配。你说你正在将正则表达式应用于街道地址。如果地址不是以门牌号开头,#将不匹配任何内容 - 也就是说,它将报告成功匹配,所述匹配由地址中第一个字符前面的空字符串组成。 / p>

对你来说无关紧要,你只是用另一个空字符串替换它。但为什么还要费心去做呢?如果您将正则表达式更改为^\d*,它将报告失败的匹配项,并且不会执行替换。结果是相同的两种方式,但“匹配注意”场景(^\d+)导致许多“不匹配”场景避免的额外工作。在高吞吐量的情况下,这可以节省生命。

其他两个正则表达式带来了额外的复杂性:^\d*可以匹配字符串末尾的连字符(例如\d*-?\d*$,甚至"123-");并且"-"可以匹配字符串中任何位置的哈希符号,而不仅仅是公寓/办公室编号的一部分。你知道你的数据,所以你可能知道这些问题都不会出现;我只是确保你知道它们。我的正则表达式\# ?\d*处理尾随连字符问题,\d+(?:-\d+)?$至少确保哈希符号后面有数字。

答案 2 :(得分:0)

我认为如果你把它们组合在一个单独的gsub()正则表达式中,作为一个替代,
它改变了起始搜索位置的上下文。

例如,这些行中的每一行都从前一个结果的开头开始 正则表达式替换 s/^\d*//g
s/\d*-?\d*$//g
s/\# ?\d*//g

和这个 s/^\d*|\d*-?\d*$|\# ?\d*//g
继续搜索/替换最后一个匹配的位置,并可能产生不同的总输出,特别是因为许多子表达式搜索类似的 如果不是相同的字符,只能用线锚来区分。

我认为你的正则表达式在这种情况下足够独特,当然也可以改变顺序 改变结果。