我正在编写一个可以有两种潜在输入形式的函数:
This is {a {string}}
This {is} a {string}
我调用用大括号“tags”包装的子字符串。我可能在字符串中有任意数量的标签,它们可以任意嵌套。
我已经尝试编写一个正则表达式来抓取标签,这当然在嵌套标签上失败,抓住{a {string}
,缺少第二个花括号。我可以把它看作一个递归问题,但是在盯着错误的答案太久之后,我觉得我看到的东西看起来很明显。
我可以做些什么来将潜在的标签分成几部分,以便处理和替换它们?
更复杂的版本
def parseTags( oBody, szText )
if szText.match(/\{(.*)\}/)
szText.scan(/\{(.*)\}/) do |outers|
outers.each do |blah|
if blah.match(/(.*)\}(.*)\{(.*)/)
blah.scan(/(.*)\}(.*)\{(.*)/) do |inners|
inners.each do |tags|
szText = szText.sub("\{#{tags}\}", parseTags( oBody, tags ))
end
end
else
szText = szText.sub("\{#{blah}\}", parseTags( oBody, blah ))
end
end
end
end
if szText.match(/(\w+)\.(\w+)(?:\.([A-Za-z0-9.\[\]": ]*))/)
func = $1+"_"+$2
begin
szSub = self.send func, oBody, $3
rescue Exception=>e
szSub = "{Error: Function #{$1}_#{$2} not found}"
$stdout.puts "DynamicIO Error Encountered: #{e}"
end
szText = szText.sub("#{$1}.#{$2}#{$3!=nil ? "."+$3 : ""}", szSub)
end
return szText
end
这是修修太久的结果。它不干净,但它确实适用于类似于“1”的案例 - {help.divider.red.sys.["{pc.login}"]}
被替换为---------------[ Duwnel ]---------------
。然而,{pc.attr.str.dotmode} {ansi.col.red}|{ansi.col.reset} {pc.attr.pre.dotmode} {ansi.col.red}|{ansi.col.reset} {pc.attr.int.dotmode}
闪烁着辉煌,随机的红色条纹和缺失的文字样片。
为了解释,标记为{ansi.col.red}
的任何内容都标记为ansi red代码,重置会转义颜色块,{pc.attr.XXX.dotmode}
会在“o”中显示1到10之间的数字。
答案 0 :(得分:2)
正如其他人所说,这是解析引擎的完美案例。正则表达式不倾向于很好地处理嵌套对。
Treetop是一个很棒的PEG解析器,您可能有兴趣看看。主要思想是在规则中定义要解析的所有内容(包括空格)。规则允许您递归地解析括号对之类的东西。
这是一个用于从嵌套括号对创建字符串数组的示例语法。通常语法是在一个单独的文件中定义的,但为了简单起见,我在最后包含了语法并用Ruby的DATA
常量加载了它。
require 'treetop'
Treetop.load_from_string DATA.read
parser = BracketParser.new
p parser.parse('This is {a {string}}').value
#=> ["This is ", ["a ", ["string"]]]
p parser.parse('This {is} a {string}').value
#=> ["This ", ["is"], " a ", ["string"]]
__END__
grammar Bracket
rule string
(brackets / not_brackets)+
{
def value
elements.map{|e| e.value }
end
}
end
rule brackets
'{' string '}'
{
def value
elements[1].value
end
}
end
rule not_brackets
[^{}]+
{
def value
text_value
end
}
end
end
答案 1 :(得分:1)
我建议你不要在这个问题中使用更复杂的正则表达式,而是要研究一下Ruby的基于语法的解析引擎。可以在大多数这些语法中设计递归和嵌套语法。
parslet
可能是您解决问题的好地方。类似erb的示例虽然没有展示嵌套,但可能最符合您的需求:https://github.com/kschiess/parslet/blob/master/example/erb.rb