如何替换模板占位符中的单词

时间:2017-05-30 18:10:53

标签: ruby regex

我试图编写一个正则表达式来替换{#1}}和#34;某些人"。

我正在使用正则表达式,因为我想修改它,以便我不必担心<%= Name %>=之间的空格以及{{1在NameE

我试过了:

Name

打印出%>时,字符串不变。我的正则表达式有什么问题?

3 个答案:

答案 0 :(得分:2)

在您的正则表达式中,您添加了\A\z个锚点。如果字符串仅包含<%= Name %>之前或之后没有任何内容,则这些确保仅匹配正则表达式。

要在字符串中的任何位置匹配您的模式,您只需删除锚点:

parsed_body = body.gsub(/<%= Name %>/, "Some person")

答案 1 :(得分:1)

看起来你正在尝试编写自己的模板解析器,这需要更多的麻烦,值得考虑已经存在的那些。

然而,这是这样一个基本想法:

erb = <<EOT
Owner: <%= name %>
Location: <%= address %>
EOT

FIELD_DATA = {
  name: 'Olive Oyl',
  address: '5 Sweethaven Village'
}

FIELD_RE = Regexp.union(FIELD_DATA.keys.map(&:to_s)).source # => "name|address"

puts erb.gsub(/<%=\s+(#{FIELD_RE})\s+%>/) { |k|
  k # => "<%= name %>", "<%= address %>"
  k[/\s+(\S+)\s+/, 1]  # => "name",        "address"
  FIELD_DATA[k[/\s+(\S+)\s+/, 1].to_sym]  # => "Olive Oyl",   "5 Sweethaven Village"
}

运行时输出:

Owner: Olive Oyl
Location: 5 Sweethaven Village

这是有效的,因为gsub可以采用正则表达式和块。对于表达式的每个匹配,它在匹配中传递给块,然后用于返回被替换的实际值。

如果您有很多目标值,而不是使用Regexp.union,请使用RegexpTrie gem。有关详细信息,请参阅“Is there an efficient way to perform hundreds of text substitutions in Ruby?”。

同样,模板解析器存在,它们已经存在了很长时间,它们经过了很好的测试,它们处理了你没有想过的边缘情况,所以不要写一个新的部分实现的,而不是重用现有的。

答案 2 :(得分:1)

考虑我假设你正在努力实现的目标,只是另一种选择

tag_pattern = /(?<open_tag><%=\s*)(?<key>(\w+))(?<close_tag>\s*%>)/
body = <<-B
   Hello, 
    My name is <%= Name %> and I know some things. Just because I am a 
    <%= Occupation %> doesn't mean I know everything, but I sure can 
    <%=Duty%> just as well as anyone else.
    Also please don't replace <%= This %>

  Thank you,
    <%= Name %>
B
dict = {"Name" => "engineersmnky", "Occupation" => "Monkey", "Duty" => "drive a train"} 

 body.gsub(tag_pattern) {|m| dict[$2] || m }
 #=>  Hello, 
 #   My name is engineersmnky and I know some things. Just because I am a 
 #   Monkey doesn't mean I know everything, but I sure can 
 #   drive a train just as well as anyone else.
 #   Also please don't replace <%= This %>
 #
 # Thank you,
 #   engineersmnky

在这种情况下,我使用了要替换的“erb”的预期部分的字典,并使用String#gsub的块样式来处理$2是命名捕获{{1}的替换}}。当没有匹配的密钥时,它只是保持匹配,例如, key

您可以使用您选择的任何模式实现此功能,但如果您打算使用“erb”样式行,则可以尝试利用"Also please don't replace <%= This %>"其他方式同样适用于以下方式:

erb

只要您正确定义tag_pattern = (?<open_tag>{!!\s*)(?<key>(\w+))(?<close_tag>\s*!\?}) body = <<-B Hello, My name is {!! Name !?} and I know some things. Just because I am a {!! Occupation !?} doesn't mean I know everything, but I sure can {!!Duty !?} just as well as anyone else. Thank you, {!! Name !?} B ,替换就相当简单。 Rubular Example