1

我刚刚开始玩 Ruby,但我遇到了一些问题。实例化后是否有一些技巧可以修改casefold attributeRegexp 对象的属性?

我尝试过的最好的想法如下:

irb(main):001:0> a = Regexp.new('a')
=> /a/
irb(main):002:0> aA = Regexp.new(a.to_s, Regexp::IGNORECASE)
=> /(?-mix:a)/i

但以下似乎都不起作用:

irb(main):003:0> a =~ 'a'
=> 0
irb(main):004:0> a =~ 'A'
=> nil
irb(main):005:0> aA =~ 'a'
=> 0
irb(main):006:0> aA =~ 'A'
=> nil

我不明白的事情正在这里发生。第 8 行的“i”在哪里?

irb(main):07:0> aA = Regexp.new(a.to_s, Regexp::IGNORECASE)
=> /(?-mix:a)/i
irb(main):08:0> aA.to_s
=> "(?-mix:a)"
irb(main):09:0>

我正在使用 Ruby 1.9.3。

我也无法理解以下代码:为什么要返回false

/(?i:a)/.casefold?      #=> false
4

3 回答 3

2

由于结果to_s只是正则表达式字符串本身 - 没有分隔符或外部标志 - 标志被转换为(?i:...)在表达式本身内部临时设置或清除它们的语法。这使您可以Regexp通过匹配相同字符串的简单Regexp.new(s)调用来获取对象。

不幸的是,包装包括明确清除对象上设置的标志。因此,您的第一个正则表达式被字符串化为介于两者之间(?:-i...)的内容 - 也就是说,该casefold选项在括号之间显式关闭。为对象重新打开它没有任何效果。

您可以使用a.source而不是a.to_s仅获取原始表达式,而无需标志设置:

irb(main):001:0> a=/a/
=> /a/
irb(main):002:0> aA = Regexp.new(a.source, Regexp::IGNORECASE)
=> /a/i
irb(main):003:0> a =~ 'a'
=> 0
irb(main):004:0> a =~ 'A'
=> nil
irb(main):005:0> aA =~ 'a'
=> 0
irb(main):006:0> aA =~ 'A'
=> 0
于 2013-01-19T11:53:28.003 回答
2

正如您的控制台输出所示,a.to_s包括区分大小写作为子表达式的选项,因此aA被定义为

/(?-mix:a)/i

所以你要求 ruby​​ 提供一个不区分大小写的正则表达式,但唯一不区分大小写的正则表达式是打开区分大小写时的组,所以最终效果是 'a' 区分大小写

于 2013-01-19T12:02:25.170 回答
1

正如 Frederick 已经解释的那样,调用to_s正则表达式将在其周围添加修饰符,以确保保留其属性(如区分大小写)。因此,如果您将区分大小写的正则表达式插入到不区分大小写的正则表达式中,插入的部分仍将区分大小写。同样,如果第一个参数是正则表达式或调用 to_s 的结果,则给予 Regexp.new 的修饰符将无效。

要解决此问题,请调用source正则表达式而不是to_s. 与 不同to_ssource只需返回正则表达式的源而不添加任何内容:

aA = Regexp.new(a.source, Regexp::IGNORECASE)

我也无法理解下面的代码:为什么返回 false:

/(?i:a)/.casefold? 

因为在本地(?i:...)设置标志,而不是全局设置。i它仅适用于括号内的正则表达式部分,而不适用于整个正则表达式。当然,在这种情况下,整个正则表达式都在括号内,但就方法casefold?而言,这并不重要。

于 2013-01-19T12:22:20.717 回答