从文件读取变量并替换

时间:2017-07-30 06:05:02

标签: ruby

我有一个Apache2服务器端包含文件。它看起来像(实际数据编辑):

<!--#set var="FIRST_VAR" value="HI" -->
<!--#set var="SECOND_VAR" value"THERE" -->
<!--#set var="FINAL_VAR" value="HEY/${FIRST_VAR}/${SECOND_VAR}/${FINAL_VAR}" -->

我想做的是与命名变量进行正则表达式匹配,然后使用哈希构建嵌套变量。例如:

@SSI["FIRST_VAR"] = "HI"
@SSI["SECOND_VAR"] = "THERE"
@SSI["FINAL_VAR"] = "HEY/HI/THERE"

我对如何正确地做到这一点感到茫然。

2 个答案:

答案 0 :(得分:2)

如果您的字符串等于文件的文本:

txt = <<-TXT
<!--#set var="FIRST_VAR" value="HI" -->
<!--#set var="SECOND_VAR" value="THERE" -->
<!--#set var="FINAL_VAR" value="HEY/${FIRST_VAR}/${SECOND_VAR}/${FINAL_VAR}" -->
TXT

(另请注意,我在第二行=之后添加了value

然后你可以像这样构建一个正则表达式:

result = txt.scan /<!--#set var=\"(.+)\" value=\"(.+)\" -->/
# =>
# [["FIRST_VAR", "HI"],
#  ["SECOND_VAR", "THERE"],
#  ["FINAL_VAR", "HEY/${FIRST_VAR}/${SECOND_VAR}/${FINAL_VAR}"]
# ]

正则表达式与文件中包含的格式基本相同,除了报价转义以及使用(.+)定义匹配组。

虽然正则表达式可能更好,但您也可以使用split采用更强力的方式:

txt.split("\n").map do |line|
  var, rest = line.split("var=\"")[1].split("\" value=\"")
  value = rest.split("\"")[0]
  [var, value]
end

答案 1 :(得分:2)

假设您将文件读入字符串,将字符串分隔为行,并从每行的末尾删除空格。

arr =<<_.lines.map(&:strip)
<!--#set var="V1" value="HI" -->
<!--#set var="V2" value="THERE" -->
<!--#set var="FV" value="HEY/${V1}/${V2}" -->
_
  #=> ["<!--#set var=\"V1\" value=\"HI\" -->",
  #    "<!--#set var=\"V2\" value=\"THERE\" -->",
  #    "<!--#set var=\"FV\" value=\"HEY/${V1}/${V2}\" -->"]

我将使用以下正则表达式。

r1 = /
     (?<=\svar=\")   # match ' var="' in a positive lookbehind
     .+?             # match one or more characters lazily
     (?=\")          # match '"' in a positive lookahead
     /x              # free-spacing regex definition mode

r2 = /
     (?<=\svalue=\") # match ' value"' in a positive lookbehind
     .+?             # match one or more characters lazily
     (?=\")          # match '"' in a positive lookahead
     /x              # free-spacing regex definition mode

r3 = /
     \/\$\{          # match '/${'
     \w+             # match one or more word characters
     \}              # match '}'
     /x              # free-spacing regex definition mode

r4 = /
     (?<=\/\$\{)     # match '/${' in a positive lookbehind
     .+?             # match any number of character, lazily
     (?=\})          # match `}` in a positive lookahead
     /x              # free-spacing regex definition mode

然后我们可以按如下方式计算所需的返回值。

g = arr.each_with_object({}) do |s,h|
  var   = s[r1].strip
  value = s[r2].strip
  h["\/\$\{#{var}\}"] = value.gsub(r3) { |s| h.key?(s) ? "/#{h[s]}" : "" }
end
  #=> {"/${V1}"=>"HI", "/${V2}"=>"THERE", "/${FV}"=>"HEY/HI/THERE"}

最后,修改密钥。

g.each_with_object({}) { |(k,v),h| h[k[r4]] = v }
  #=> {"V1"=>"HI", "V2"=>"THERE", "FV"=>"HEY/HI/THERE"}

上述两个表达当然可以链接。事实上,它可以写成一行,但我不推荐它。