Ruby如何删除字符串内括号数量匹配的括号包裹单词子串
Ruby 删除平衡括号包裹单词子串实现方案
需求描述
需要删除字符串中所有满足以下规则的子串:
- 子串以任意非零数量的左括号开头
- 之后跟随任意数量的单词字符(匹配
\w规则) - 最后跟随与开头左括号数量相等的右括号
初始尝试与问题
纯正则表达式默认无法直接匹配数量对等的左右括号,最初尝试通过动态反向引用实现匹配,以下为思路展示(非合法Ruby代码):
sttrep = str.gsub(/([(]+) \w+ [)]#{\1.size}/x, '')
上述代码中\1.size的写法不符合Ruby语法,无法直接通过正则插值实现基于反向引用的动态长度匹配。
另一种思路是循环调用gsub逐层剥离括号:
tmpstr = str loop do strrep = tmpstr.gsub(/[(] ([(]\w+[)]) [)]/x, "(\\1)") if tmpstr == strrep # 仅剩余一层括号待处理 sttrep = str.gsub(/[(]\w+[)]/x, '') break else tmpstr = strrep end end # strrep即为最终结果字符串
该方案可以得到正确结果,但实现逻辑冗余,希望找到更简洁的实现方式,避免手动编写逐字符遍历的括号计数解析器。
测试示例
- 示例1
str = "ab((((cd))))ef((gh))ij(kl)mn" # 预期处理结果:abefijmn
- 示例2
str = "((((abc));def;((ghi)))" # 预期处理结果:(;def;)
最优实现:递归正则
Ruby 2.0+ 版本使用的Onigmo正则引擎支持子表达式递归调用,仅需一行代码即可完成匹配替换:
strrep = str.gsub(/\((?:\w+|\g<0>)\)/, '')
正则说明
\(匹配左括号(?:\w+|\g<0>)非捕获组,匹配两种内容:要么是纯单词字符,要么递归匹配整个正则规则本身(即嵌套的平衡括号结构)\)匹配右括号
该正则会自动匹配所有层数对等、内层为单词字符的括号结构,全局替换为空即可得到预期结果,两个示例均可完美通过验证。
内容的提问来源于stack exchange,提问作者user1934428
相关产品推荐
相关产品推荐

