what is the meaning of "#$e" in ruby 2.1.2 - ruby-on-rails

I have one string which is contain char like "Pi#$e77L09!($".
But when i tried to print on Console its prints like "Pi!($"
2.1.2 :002 > str = "Pi#$e77L09!($" => "Pi!($"
2.1.2 :003 > puts str Pi!($ => nil

The magic is in #. As you know "#{ ruby code }" executes the code in the block and prints it. Similarly, # allows you to access global variables of a program by putting a hash in front of it like so "#$a".
so if you try this code.
$a = 'test'
puts "#$a"
you will see that it prints test. So in your case since $e77L09 is a non-existent global variable it prints nothing.
if you want to print that string as a string you will need to print it in single quotes. 'Pi#$e77L09!($'
The above usage of "#$1 #$2" is really useful when you use regex. When a string has multiple matching regex it becomes accessible using $1, $2, $3, etc. This stuff came from the Perl world I believe (I am not 100% sure about its history).
EDIT: Like Global Variable supports class and instance variables can be accessed as well.

try
puts 'Pi#$e77L09!($'
'#' is the special character which uses for interpolation of string in ruby.
if you use 'Pi#$e77L09!($' it will add \ String Literals before the '#'

Related

Rails remove '\' from json response

json response
{"skill"=>"{\"dept_id\"=>\"01\", \"user_id\"=>\"001\", \"level_cd\"=>\"04_swim\", \"first_name\"=>\"rohit\", \"last_name\"=>\"patel\", \"dept_full_name\"=>\"swiming\", \"rank\"=>\"04_swim\"}, {\"dept_id\"=>\"02\", \"user_id\"=>\"002\", \"level_cd\"=>\"04_swim\", \"first_name\"=>\"ranjit\", \"last_name\"=>\"shinde\", \"dept_full_name\"=>\"running\", \"rank\"=>\"03_run\"}, {\"dept_id\"=>\"04\", \"user_id\"=>\"004\", \"level_cd\"=>\"02_jump\", \"first_name\"=>\"kedar\", \"last_name\"=>\"patil\", \"dept_full_name\"=>\"jumping\", \"rank\"=>\"02_jump\"}, {\"dept_id\"=>\"05\", \"user_id\"=>\"005\", \"level_cd\"=>\"03_run\", \"first_name\"=>\"kapil\", \"last_name\"=>\"bote\", \"dept_full_name\"=>\"Hammer\", \"rank\"=>\"03_run\"}"
How to remove only \ from this response
expected output is
"skill"=>{"dept_id"=>"01", "user_id"=>"001", "level_cd"=>"04_swim", "first_name"=>"rohit", "last_name"=>"patel", "dept_full_name"=>"swiming", "rank"=>"04_swim"}, {"dept_id"=>"02", "user_id"=>"002", "level_cd"=>"04_swim", "first_name"=>"ranjit", "last_name"=>"shinde", "dept_full_name"=>"running", "rank"=>"03_run"}, {"dept_id"=>"04", "user_id"=>"004", "level_cd"=>"02_jump", "first_name"=>"kedar", "last_name"=>"patil", "dept_full_name"=>"jumping", "rank"=>"02_jump"}, {"dept_id"=>"05", "user_id"=>"005", "level_cd"=>"03_run", "first_name"=>"kapil", "last_name"=>"bote", "dept_full_name"=>"Hammer", "rank"=>"03_run"}
There are currently no backslashes in the string. The backslash is only there because the context is within a double quoted string context.
If you want to use a double quote in double quoted string context you need to escape it with a backslash, otherwise the compiler thinks you want to end the string.
"John Doe said: "Hello Word!""
The above is not valid. The " before Hello World! will end the string. Meaning that Hello World! will not be in string context and Ruby tries to parse Hello and World as constants.
To prevent this from happening you escape the " with a backslash \.
"John Doe said: \"Hello Word!\""
\" will be interpreted as one " character. There is no backslash present within the resulting string. See the Ruby literals documentation.
When using single quotes for string delimiters there is no need to escape the double quotes (but you do need to escape single quotes). The above could also be written as:
'John Doe said: "Hello Word!"'
Similarly your data can be written as:
{"skill"=>'{"dept_id"=>"01", "user_id"=>"001", "level_cd"=>"04_swim", "first_name"=>"rohit", "last_name"=>"patel", "dept_full_name"=>"swiming", "rank"=>"04_swim"}, {"dept_id"=>"02", "user_id"=>"002", "level_cd"=>"04_swim", "first_name"=>"ranjit", "last_name"=>"shinde", "dept_full_name"=>"running", "rank"=>"03_run"}, {"dept_id"=>"04", "user_id"=>"004", "level_cd"=>"02_jump", "first_name"=>"kedar", "last_name"=>"patil", "dept_full_name"=>"jumping", "rank"=>"02_jump"}, {"dept_id"=>"05", "user_id"=>"005", "level_cd"=>"03_run", "first_name"=>"kapil", "last_name"=>"bote", "dept_full_name"=>"Hammer", "rank"=>"03_run"}'
The above clearly demonstrates that there are no backslash characters present in the string.
However the string is not JSON. I suggest changing the server response if possible. You can eval the current response, but I would advise not to use eval ever (eval is evil). If the server would send malicious Ruby code, eval will execute it without any issues and might corrupt your machine.
Looks like the hash example needs to end with an } to be valid. So I added it in my example. Further more it looks to be a collection of records, but it also looks like it's missing a list. If it were inside a list it would be valid but as the example stands now, it is not a valid hash.
But let's say just for fun, I did want to take the string and put it inside an array. Maybe something like this:
data = {"skill"=>"{\"dept_id\"=>\"01\", \"user_id\"=>\"001\", \"level_cd\"=>\"04_swim\", \"first_name\"=>\"rohit\", \"last_name\"=>\"patel\", \"dept_full_name\"=>\"swiming\", \"rank\"=>\"04_swim\"}, {\"dept_id\"=>\"02\", \"user_id\"=>\"002\", \"level_cd\"=>\"04_swim\", \"first_name\"=>\"ranjit\", \"last_name\"=>\"shinde\", \"dept_full_name\"=>\"running\", \"rank\"=>\"03_run\"}, {\"dept_id\"=>\"04\", \"user_id\"=>\"004\", \"level_cd\"=>\"02_jump\", \"first_name\"=>\"kedar\", \"last_name\"=>\"patil\", \"dept_full_name\"=>\"jumping\", \"rank\"=>\"02_jump\"}, {\"dept_id\"=>\"05\", \"user_id\"=>\"005\", \"level_cd\"=>\"03_run\", \"first_name\"=>\"kapil\", \"last_name\"=>\"bote\", \"dept_full_name\"=>\"Hammer\", \"rank\"=>\"03_run\"}"}
parsed_data = data["skill"].split("}, ").map{|x| x.end_with?("\"") ? x + '}' : x}.map{|x| eval(x)}
puts parsed_data
{"dept_id"=>"01", "user_id"=>"001", "level_cd"=>"04_swim", "first_name"=>"rohit", "last_name"=>"patel", "dept_full_name"=>"swiming", "rank"=>"04_swim"}
{"dept_id"=>"02", "user_id"=>"002", "level_cd"=>"04_swim", "first_name"=>"ranjit", "last_name"=>"shinde", "dept_full_name"=>"running", "rank"=>"03_run"}
{"dept_id"=>"04", "user_id"=>"004", "level_cd"=>"02_jump", "first_name"=>"kedar", "last_name"=>"patil", "dept_full_name"=>"jumping", "rank"=>"02_jump"}
{"dept_id"=>"05", "user_id"=>"005", "level_cd"=>"03_run", "first_name"=>"kapil", "last_name"=>"bote", "dept_full_name"=>"Hammer", "rank"=>"03_run"}
Now with the data in an array you can convert it to json if you'd like
require 'json'
2.6.5 :007 > parsed_data.to_json
=> "[{\"dept_id\":\"01\",\"user_id\":\"001\",\"level_cd\":\"04_swim\",\"first_name\":\"rohit\",\"last_name\":\"patel\",\"dept_full_name\":\"swiming\",\"rank\":\"04_swim\"},{\"dept_id\":\"02\",\"user_id\":\"002\",\"level_cd\":\"04_swim\",\"first_name\":\"ranjit\",\"last_name\":\"shinde\",\"dept_full_name\":\"running\",\"rank\":\"03_run\"},{\"dept_id\":\"04\",\"user_id\":\"004\",\"level_cd\":\"02_jump\",\"first_name\":\"kedar\",\"last_name\":\"patil\",\"dept_full_name\":\"jumping\",\"rank\":\"02_jump\"},{\"dept_id\":\"05\",\"user_id\":\"005\",\"level_cd\":\"03_run\",\"first_name\":\"kapil\",\"last_name\":\"bote\",\"dept_full_name\":\"Hammer\",\"rank\":\"03_run\

How do I get lua string match to parse an environment variable string?

I have a config file parser written in lua.
I'd like to detect values that are environment variables and change them with os.getenv.
It's probably a bit ambitious because I can have values like
"a string with an embedded ${VARIABLE} in here"
or
"another string with an env $VARIABLE"
And I should probably allow escaping them with double $$ to allow a literal $.
How do I do this?
This is what I have so far, but it isn't right
local envvar = string.match(value, "%$([%w_]+)")
if envvar then
print("Envvar=", envvar)
value = value:gsub("(%$[%w_]+)", os.getenv(envvar))
end
For example, I can't figure out how to use the %b balance option here to properly match { } combinations. And make them optional. How do I make this work robustly?
In fact, I realise it's probably more complicated than this. What if more than one environment variable was specified?
local text = [[
Example: ${LANG}, $TEXTDOMAINDIR, $$10.00, $$LANG, $UNDEFINED
Nested braces: {{${SHELL}}}
]]
text = text:gsub('$%$','\0')
:gsub('${([%w_]+)}', os.getenv)
:gsub('$([%w_]+)', os.getenv)
:gsub('%z','$')
print(text)
--> Example: en_US.UTF-8, /usr/share/locale/, $10.00, $LANG, $UNDEFINED
--> Nested braces: {{/bin/bash}}

Accessing Ruby Hash value using a string

I have a ruby array like below
tomcats = [
'sandbox',
'sandbox_acserver',
'sandbox_vgw'
]
I need to pass the string as a hash index like below
tomcats.each do |tomcat_name|
obi_tomcat '#{tomcat_name}' do
Chef::Log::info("Creating tomcat instance - #{tomcat_name}")
Chef::Log::info("#{node['obi']['tomcat']['sandbox'][:name]}") // works
Chef::Log::info("#{node['obi']['tomcat']['#{tomcat_name}'][:name]}") // doesn't work
end
end
The last log throws an error since the access with #{tomcat_name} is nil. I'm new to ruby. How do I access with key as the tomcat_name ?
In normal code, you'd write:
node['obi']['tomcat'][tomcat_name][:name]
In a string interpolation (useless here, because it's the only thing in the string in this case), it is completely the same:
"#{node['obi']['tomcat'][tomcat_name][:name]}"
#{} only works in double quote, as "#{tomcat_name}".
But you don't need the syntax here, just use [tomcat_name] directly.
When I saw this question, I'm thinking whether ruby placeholder could be put inside other placeholder in string interpolation. And I found that ruby actually support it, and most interesting thing is that you don't need to escape the " inside the string.
Although it is not very useful in this case, it still works if you write as below:
Chef::Log::info("#{node['obi']['tomcat']["#{tomcat_name}"][:name]}")
Below is an simple example of placeholder inside other placeholder:
tomcats = [
'sandbox',
'sandbox_acserver',
'sandbox_vgw'
]
node = {
'sandbox_name' => "sandbox name",
'sandbox_acserver_name' => "sandbox_acserver name",
'sandbox_vgw_name' => "sandbox_vgw name",
}
tomcats.each do | tomcat |
puts "This is tomcat : #{node["#{tomcat}_name"]}"
end

ruby regex with quotes

I'm trying to pass more than one regex parameter for parts of a string that needs to be replaced. Here's the string:
str = "stands in hall "Let's go get to first period everyone" Students continue moving to seats."
Here is the expected string:
str = "stands in hall "Let's go get to first period everyone" Students continue moving to seats."
This is what I tried:
str.gsub(/'|"/, "'" => "\'", """ => "\"")
This is what I got:
"stands in hall \"Let's go get to first period everyone\" Students continue moving to seats."
How do I get the quotes in while sending in two regex parameters using gsub?
This is an HTML unescaping problem.
require 'cgi'
CGI.unescape_html(str)
This gives you the correct answer.
From my comments on this question:
Your updated version is correct. The only reason the slashes are in your final line of code is that it's an escape sequence so that you don't mistakenly think the first slash is used to terminate the string. Try assigning your output and printing it:
str1 = str.gsub(/'|"/, "'" => "\'", """ => "\"")
puts str1
and you'll see that the slashes are gone when str1 is printed using puts.
The difference is that autoevaluating variables within irb (which is what I assume you're doing to execute this sample code) automatically calls the inspect method, which for string variables shows the string in its entirety.
Because I did not understand unescaping characters I found an alternative solution that might be the "rails-way"
Can you use <%= raw 'some_html' %>
My final solution ended up being this instead of messy regex and requiring CGI
<%= raw evidence_score.description %>
Unescaping HTML string in Rails

Regex in Ruby: expression not found

I'm having trouble with a regex in Ruby (on Rails). I'm relatively new to this.
The test string is:
http://www.xyz.com/017010830343?$ProdLarge$
I am trying to remove "$ProdLarge$". In other words, the $ signs and anything between.
My regular expression is:
\$\w+\$
Rubular says my expression is ok. http://rubular.com/r/NDDQxKVraK
But when I run my code, the app says it isn't finding a match. Code below:
some_array.each do |x|
logger.debug "scan #{x.scan('\$\w+\$')}"
logger.debug "String? #{x.instance_of?(String)}"
x.gsub!('\$\w+\$','scl=1')
...
My logger debug line shows a result of "[]". String is confirmed as being true. And the gsub line has no effect.
What do I need to correct?
Use /regex/ instead of 'regex':
> "http://www.xyz.com/017010830343?$ProdLarge$".gsub(/\$\w+\$/, 'scl=1')
=> "http://www.xyz.com/017010830343?scl=1"
Don't use a regex for this task, use a tool designed for it, URI. To remove the query:
require 'uri'
url = URI.parse('http://www.xyz.com/017010830343?$ProdLarge$')
url.query = nil
puts url.to_s
=> http://www.xyz.com/017010830343
To change to a different query use this instead of url.query = nil:
url.query = 'scl=1'
puts url.to_s
=> http://www.xyz.com/017010830343?scl=1
URI will automatically encode values if necessary, saving you the trouble. If you need even more URL management power, look at Addressable::URI.

Resources