Reputation: 1541
I have an Apache2 server side include file. It looks like (actual data redacted):
<!--#set var="FIRST_VAR" value="HI" -->
<!--#set var="SECOND_VAR" value"THERE" -->
<!--#set var="FINAL_VAR" value="HEY/${FIRST_VAR}/${SECOND_VAR}/${FINAL_VAR}" -->
What I'd like to do is to do a regex match with named variables, and then build the nested variables using a hash, perhaps. Example:
@SSI["FIRST_VAR"] = "HI"
@SSI["SECOND_VAR"] = "THERE"
@SSI["FINAL_VAR"] = "HEY/HI/THERE"
I'm at a loss on how to do this properly.
Upvotes: 1
Views: 57
Reputation: 110725
Suppose you read the file into a string, separate the string into lines and strip whitespace from the ends of each line.
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}\" -->"]
I will use the following regular expressions.
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
We can then compute the desired return value as follows.
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"}
Lastly, modify the keys.
g.each_with_object({}) { |(k,v),h| h[k[r4]] = v }
#=> {"V1"=>"HI", "V2"=>"THERE", "FV"=>"HEY/HI/THERE"}
The two above expressions could of course be chained. In fact, it could be written as a single line, but I wouldn't recommend it.
Upvotes: 2
Reputation: 26778
If you have a string equal to the text of the file:
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
(also note I've added an =
after value
in the second line)
Then you can build a regex like so:
result = txt.scan /<!--#set var=\"(.+)\" value=\"(.+)\" -->/
# =>
# [["FIRST_VAR", "HI"],
# ["SECOND_VAR", "THERE"],
# ["FINAL_VAR", "HEY/${FIRST_VAR}/${SECOND_VAR}/${FINAL_VAR}"]
# ]
The regex is basically the same format as that contained in the file, except quotations are escaped and the match groups are defined using (.+)
.
Although regex is probably better, you could also take a more brute-force style approach using split
:
txt.split("\n").map do |line|
var, rest = line.split("var=\"")[1].split("\" value=\"")
value = rest.split("\"")[0]
[var, value]
end
Upvotes: 2