How to embed regular expressions in other regular expressions in Ruby

前端 未结 2 641
鱼传尺愫
鱼传尺愫 2020-12-07 01:37

I have a string:

\'A Foo\'

and want to find \"Foo\" in it.

I have a regular expression:

/foo/

th

2条回答
  •  情歌与酒
    2020-12-07 02:21

    "what's wrong?"

    Your assumption on how a Regexp is interpolated is wrong.

    Interpolation via #{...} is done by calling to_s on the interpolated object:

    d = Date.new(2017, 9, 8)
    #=> #
    
    d.to_s
    #=> "2017-09-08"
    
    "today is #{d}!"
    #=> "today is 2017-09-08!"
    

    and not just for string literals, but also for regular expression literals:

    /today is #{d}!/
    #=> /today is 2017-09-08!/
    

    In your example, the object-to-be-interpolated is a Regexp:

    foo_regex = /foo/
    

    And Regexp#to_s returns:

    [...] the regular expression and its options using the (?opts:source) notation.

    foo_regex.to_s
    #=> "(?-mix:foo)"
    

    Therefore:

    /A #{foo_regex}/i
    #=> /A (?-mix:foo)/i
    

    Just like:

    "A #{foo_regex}"
    #=> "A (?-mix:foo)"
    

    In other words: because of the way Regexp#to_s is implemented, you can interpolate patterns without loosing their flags. It's a feature, not a bug.

    If Regexp#to_s would return just the source (without options), it would work the way you expect:

    def foo_regex.to_s
      source
    end
    
    /A #{foo_regex}/i
    #=> /A foo/i
    

    The above code is just for demonstration purposes, don't do that.

提交回复
热议问题