我尝试使用StringScanner
将字符串解析为令牌以便以后处理。一切顺利,直到我测试了正则表达式语法解析。 Regexen看起来像这样:
r|hello|gmi
r:there|there:gmi
r/:(?=[jedi])[sith]:/gmi
r!hello!gmi
即r
,然后是|
(或其他几个字符,但现在不相关),其次是正则表达式的正文 - 可以包括已转义的字符,例如\|
和\\
- 然后是另一个|
,然后是正则表达式的标记。
要查找正则表达式文字,我使用的代码看起来非常像这样:
require 'strscan'
scanner = StringScanner.new('r|abc| ')
puts "pre-regex: #{scanner.inspect}"
puts "got a char: #{scanner.getch} (res: #{scanner.inspect})"
divider = scanner.getch
puts "got divider: #{divider.inspect}"
puts "mid-regex: #{scanner.inspect}"
# this bit still fails even if you replace `#{divider}' with `|'
res = scanner.scan_until(/(?<![^\\]\\)#{divider}[a-z]*/)
puts "post-regex: #{scanner.inspect}"
if scanner.skip(/\s+/)# || scanner.skip(/;-.*?-;/m)
puts "Success! #{res}"
else
puts "Fail. Ended at: #{scanner.inspect}"
puts "(res was #{res.inspect})"
end
在这里,我已经尽可能地减少它,以便我能够清楚地显示问题。在实际代码中,它是大量代码的一部分,其中绝大多数代码都不相关。我已经将这个漏洞缩小到了这一部分 - 您可以使用该链接查看它是否存在 - 但我无法弄清楚为什么这不能正确扫描到下一个|
实例,然后返回标志。
作为旁注,如果有更好的方法,请告诉我。我发现我非常喜欢StringScanner
,但那可能是因为我对regexen很着迷,以至于我称之为regexen。
TL; DR :为什么StringScanner
显然匹配,就好像它的位置是一个字符一样,我怎样才能让它正常工作?
答案 0 :(得分:1)
问题是Ruby使用字符串按原样插入正则表达式文字,例如
divider = '|'
/(?<![^\\]\\)#{divider}[a-z]*/
=> /(?<![^\\]\\)|[a-z]*/
要逃避分隔符,您可以
divider = '|'
/(?<![^\\]\\)#{Regexp.quote divider}[a-z]*/
=> /(?<![^\\]\\)\|[a-z]*/
此修改使代码通过,但您仍需要验证分隔符是否为非单词字符。