如何在Ruby中用%r <…>分隔的正则表达式中进行负向查找?

时间:2019-04-25 18:19:44

标签: regex ruby syntax syntax-error regex-lookarounds

我喜欢%r<…>分隔符,因为它非常容易发现正则表达式的开始和结束,而且我不必转义任何/。但是似乎它们有其他定界符没有的无法克服的局限性?

其他所有可以想到的分隔符都可以正常工作:

/(?<!foo)/
%r{(?<!foo)}
%r[(?<!foo)]
%r|(?<!foo)|
%r/(?<!foo)/

但是当我尝试这样做时:

%r<(?<!foo)>

它给出以下语法错误:

unterminated regexp meets end of file

好吧,它可能不喜欢它不是平衡对,但是您如何逃避它,使它喜欢呢?

是否需要逃脱某些东西?

根据wikibooks.org

  

任何单个非字母数字字符都可用作分隔符,   %[including these], %?or these?, %~or even these things~。   通过使用这种表示法,可以出现通常的字符串定界符“和”   在未转义的字符串中,但是您当然选择了新的分隔符   确实需要逃脱。

实际上,在以下示例中需要转义:

%r!(?<\!foo)!                                                             
%r?(\?<!foo)? 

但是,如果那是唯一的问题,那么我应该能够像这样逃脱它并使其起作用:

%r<(?\<!foo)>

但这会产生此错误:

undefined group option: /(?\<!foo)/

所以也许/不需要转义 wikibooks.org确实将%<pointy brackets>列为例外之一:

  

但是,如果您使用   %(parentheses), %[square brackets], %{curly brackets}或   %<pointy brackets>作为分隔符,然后使用相同的分隔符   只要它们在平衡中,就可以在字符串中显示 unscapeed   对

平衡对是否存在问题?

平衡对没有问题,只要您在正则表达式中执行需要它们的操作,例如...

%r{(?<!foo{1})}   # repetition quantifier
%r[(?<![foo])]    # character class
%r<(?<name>foo)>  # named capture group

但是,如果您需要在正则表达式中插入左侧的定界符({,[或<),该怎么办?逃脱吧? Ruby似乎在大多数情况下逃脱不平衡的定界符都没问题...

%r{(?<!foo\{)}                                                                  
%r[(?<!\[foo)]
%r<\<foo>

只是当您尝试在<!之后的“组选项”(我猜这是(?字符被分类为此处)中间进行操作时,喜欢它:

%r<(?\<!foo)>
# undefined group option: /(?\<!foo)/

那么您该如何做才能让Ruby开心呢? (无需更改定界符)

结论

解决方法很简单。我将更改此特定正则表达式,使其仅使用%r{…}之类的其他名称代替。

但是问题仍然存在...

  1. 真的没有办法逃避<吗?
  2. 真的有某些正则表达式根本无法使用某些%r<…>这样的分隔符编写吗?
  3. %r<…>是唯一存在此问题的正则表达式定界符对(其中使用某些正则表达式无法编写)。如果您知道与%r{…} / %r[…]类似的示例,请分享!

版本信息

这可能并不重要,因为此语法可能没有更改,但是我正在使用:

⟫ ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]

参考:

1 个答案:

答案 0 :(得分:0)

正如其他人所提到的那样,这似乎是基于此字符与其他成对边界的区别的疏忽。

至于“真的没有办法逃避<吗?”有办法...但是您不会喜欢它:

%r<(?#{'<'}!foo)> == %r((?<!foo))

使用插值插入<字符似乎可行。但是考虑到还有更好的选择,除非您打算将正则表达式分成几个部分,否则我将避免使用它。