【问题标题】:How to match a string from an array at the beginning of another string如何在另一个字符串的开头匹配来自数组的字符串
【发布时间】:2017-11-01 22:29:40
【问题描述】:

我想不区分大小写地匹配我数组中的一个字符串TOKENS,它位于另一个字符串的开头,后跟一个空格或行尾。

我的令牌数组如下所示:

2.4.0 :013 > TOKENS = ["m", "o"]
 => ["m", "o"]

当我尝试匹配数组中的每个元素时,它会挑选出错误的结果:

2.4.0 :009 > data_col = ["M", "b", "Mabc", "abc m b"]
 => ["M", "b", "Mabc", "abc m b"]
...
2.4.0 :015 > data_col.select{|string| string =~ /^[#{Regexp.union(TOKENS)}]([[:space:]]|$)/i }
 => ["M", "b"]

这匹配“M”和“b”条目,即使“b”没有出现在我的 TOKENS 列表中。如何修改我的正则表达式,以便只匹配正确的值“M”?

我使用的是 Ruby 2.4。

【问题讨论】:

    标签: arrays ruby regex string


    【解决方案1】:

    我会使用:

    TOKENS = ["m", "o"]
    DATA_COL = ["M", "b", "Mabc", "abc m b"]
    RE = /^(?:#{Regexp.union(TOKENS).source})(?: |$)/i
    
    DATA_COL.select{ |string| string[RE] }
    # => ["M"]
    

    稍微分解一下:

    Regexp.union(TOKENS).source # => "m|o"
    /^(?:#{Regexp.union(TOKENS).source})(?: |$)/i # => /^(?:m|o)(?: |$)/i
    

    /^[#{Regexp.union(TOKENS)}]([[:space:]]|$)/i 在循环中不是一个好主意。每次通过你强制 Ruby 创建模式;效率在循环内部很重要,尤其是大循环,因此在循环外部创建模式,然后参考内部模式。

    下一个问题是Regexp.union 有一个它应该匹配的正确大小写的概念:

    Regexp.union(TOKENS).to_s        # => "(?-mix:m|o)"
    

    (?-mix: 部分是正则表达式引擎记住模式标志的方式。当模式嵌入到另一个模式中时,他们继续知道应该寻找什么,导致我们咬牙切齿地哭泣:

    /#{Regexp.union(TOKENS)}/i # => /(?-mix:m|o)/i
    

    尾随 i 告诉模式它应该忽略大小写,但嵌入的 i 未设置,因此它尊重大小写。这就是打破你模式的原因。

    修复方法是在嵌入时使用source,就像我在上面所做的那样。

    有关详细信息,请参阅正则表达式“options”部分。

    【讨论】:

    • 另一个问题是原始正则表达式在字符类(方括号)内有替换(由Regexp.union 创建)。
    • 虽然这似乎只会导致b 在您拥有(?-mix:) 结构时错误地返回true。
    • 啊,是的,它将?-m解释为字符类中的一个字符范围,其中包括b
    • 字符集中不能发生交替,字符集中的所有字符都同等重要并且都被尊重,所以|没有特殊意义。 ?-m 不被解释为一个范围,因为 (?- 是一个标记。请参阅答案底部提到的“选项”文档。
    • 对,我的意思是Regexp.union 的输出应该是交替的,但是将它放在方括号内会使它不起作用。我确实认为它被解释为一个范围,至少在我目前开放的 Ruby 版本(2.0)中。运行 "b" =~ /^[(?-mix:m|o)]$/ 返回 0,而更改范围以排除 b(即 "b" =~ /^[(?-aix:m|o)]$/)使其返回 nil。如果这没有发生,您如何解释 'b' 与 OP 的原始正则表达式匹配?我在“选项”文档中没有看到任何解决此问题的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    相关资源
    最近更新 更多