我试图编写一个正则表达式来替换{#1}}和#34;某些人"。
我正在使用正则表达式,因为我想修改它,以便我不必担心<%= Name %>
和=
之间的空格以及{{1在Name
和E
我试过了:
Name
打印出%>
时,字符串不变。我的正则表达式有什么问题?
答案 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