I have a set of special characters for Elasticsearch that I need to escape with Ruby.
They are: + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
How can I get any string to escape any of these characters?
Thanks
The problem as it is stated has no solution, because “escaping two subsequent characters” makes no sense. What result do you expect to receive “escaping”, say, &&?
I believe, you want to escape all single characters, so that && becomes \&\& and || — \|\|. That is easy.
to_escape = %w_+ - = & | > < ! ( ) { } [ ] ^ " ~ * ? : \ /_ # C"mon, SO parser
re = Regexp.union(to_escape)
print 'str (f) | a || b'.gsub(re) { |m| "\\#{m}" }
#⇒ str \(f\) \| a \|\| b
Another possibility would be to use Regexp#escape, but it will escape more, than you probably need (e. g. spaces.)
This is a variation on #mudasobwa's answer, using the form of String#gsub that uses a hash for replacements:
escapees = %w$ + - = & | > < ! ( ) { } [ ] ^ " ~ * ? : \ / $
#=> ["+", "-", "=", "&", "|", ">", "<", "!", "(", ")", "{", "}",
# "[", "]", "^", "\"", "~", "*", "?", ":", " /"]
h = escapees.each_with_object({}) { |c,h| h[c] = "\\#{c}" }
#=> {"+"=>"\\+", "-"=>"\\-",..., " /"=>"\\ /"}
h.default_proc = ->(h,k) { k }
If the hash h does not have a key k, Hash#default_proc= causes the h[k] to to return k.
s = 'str (f) | a || b'
ss = s.gsub(/./,h)
#=> "str \\(f\\) \\| a \\|\\| b"
puts ss
#=> str \(f\) \| a \|\| b
Related
Add comma after closing bracket } using bash.
Using
sed 's/variable/&,/g;s/,$//'
adds comma after variable, however,
sed 's/}/&,/g;s/,$//'
doesn't work.
Input:
variable "policy_name1" {
description = "abc xyz"
type = string
default = [
"test1"
"test2"
]
}
variable "policy_name2" {
description = "abc xyz"
type = bool
default = false
}
Output:
variable "policy_name1" {
description = "abc xyz"
type = string
default = [
"test1"
"test2"
]
},
variable "policy_name2" {
description = "abc xyz"
type = bool
default = false
}
sed Add a comma after curly bracket, but not on last line:
sed -e '$!s/^ \{4\}}$/&,/'
$!s/ Not on last line replace
^ \{4\}}$ lines begin with 4 space, followed and terminated by }
/&,/ by matched content, followed by ,.
Will render:
variable "policy_name1" {
description = "abc xyz"
type = array
default = [
"test1"
"test2"
]
},
variable "policy_name2" {
description = "abc xyz"
type = bool
default = false
},
variable "policy_name3" {
description = "simple test string..."
type = int
default = 42
}
More complex: Add comma on each lines but not on last for each block:
sed -e ':a;N;/[^{\[(,] *\n/{/\n[ \o11]*[]})]/!s/\n/,\n/};P;D;$!ba'
Could render:
variable "policy_name1" {
description = "abc xyz",
type = array,
default = [
"test1",
"test2"
]
},
variable "policy_name2" {
description = "abc xyz",
type = bool,
default = false
},
variable "policy_name3" {
description = "simple test string...",
type = int,
default = 42
}
:a; Label "a" for furthen branch
N; Merge with next line
/[^{\[(,] *\n/ If buffer contain other than comma or open bracket, followed by newline
{ then do block:
/\n[ \o11]*[]})]/! If NOT buffer contain newline followed by space and other then close bracket
s/\n/,\n/ then place a comma before newline
}; end of block
P; print buffer up to newline
D; delete buffer up to newline
$!ba If not on last line, branch to "a"
Here is what you can do,
#!/usr/bin/env bash
FILENAME="test.tf"
COUNT=`wc -l $FILENAME | awk '{ print $1 }'`
COUNT=`expr $COUNT - 1`
sed "1,$COUNT s/}/},/" "$FILENAME"
I have provided a bash script so that we can avoid the last line in a right way. This script will append a comma whenever it finds an ending curly bracket ( } ) except for when it is last line.
I have few lines of code in a file
(code has few new lines, tabs, string and pattern-string)
I want to get this content of file as a string value,
so that it can be sent as a string value of some parameter in json
{param1: "value1", code: "code-content-from-file-should-go-here"}
lets say file content is
function string.urlDecode(str)
if string.isEmpty(str) then return str end
str = string.gsub(str, "+", " ")
str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end)
str = string.gsub(str, "\r\n", "\n")
return str
end
which should get converted to (what I see here is newline, tabs, in general code formatting is preserved, " \ etc are escaped)
function string.urlDecode(str)\n if string.isEmpty(str) then return str end\n str = string.gsub(str, \"+\", \" \")\n str = string.gsub(str, \"%%(%x%x)\", function(h) return string.char(tonumber(h, 16)) end)\n str = string.gsub(str, \"\\r\\n\", \"\\n\")\n return str\nend
So that json becomes
{param1: "value1", code: "function string.urlDecode(str)\n if string.isEmpty(str) then return str end\n str = string.gsub(str, \"+\", \" \")\n str = string.gsub(str, \"%%(%x%x)\", function(h) return string.char(tonumber(h, 16)) end)\n str = string.gsub(str, \"\\r\\n\", \"\\n\")\n return str\nend"}
While conversion of file-content to string in above mentioned manner can be done
using sed (got from few related slackoverflow threads like How can I replace a newline (\n) using sed?),
but I will have to handle each scenario like newline, tabs, ", \, and if there are any other special characters that needs to be escaped (which I dont know)
Is there any bash command (or maybe python module) that can handle all such scenario's for code-content-from-file to string conversion?
As this sees like a common use case if someone wants to send code content in JSON
If content is in file.txt
function encode {
local input=$1
local output
for ((i=0;i<${#input};i+=1)); do
ic=${input:$i:1}
if [[ $ic = $'\n' ]]; then
oc='\n'
elif [[ $ic = '\' || $ic = '"' ]]; then
oc='\'$ic
# [[ $ic < $'\040' ]] # works only if LC_COLLATE=C or LC_ALL=C
elif (( $(printf "%d" "'$ic") < 32 )); then
oc='\0'$(printf "%02o" "'$ic")
else
oc=$ic
fi
output=$output$oc
done
echo "$output"
}
printf '{param1: "%s", code: "%s"}' "value1" "$(encode "$(<file.txt)")"
I need to remove white spaces after some characters, not all of them. I want to remove whites spaces after these chars: I,R,P,O. How can I do it?
"I ".gsub(/(?<=[IRPO]) /, "") # => "I"
"A ".gsub(/(?<=[IRPO]) /, "") # => "A "
" P $ R 3I&".gsub(/([IRPO])\s+/,'\1')
#=> " P$ R3I&"
I have a string: results = "123 456 "
I would like to iterate through the string and print: "1,2,3, ,4,5,6, "
This is my code thus far:
results.each do |k|
print k, ","
end
I have also tried using each_char.
This should work:
results.split('').join(',')
# => "1,2,3, ,4,5,6, "
results.each_char.map
# => ["1", "2", "3", " ", "4", "5", "6", " "]
Or, if you want a string as output:
result.each_char.map.join(',')
# => "1,2,3, ,4,5,6, "
each_char works for me:
results = "123 456 "
results.each_char do |char|
print "#{char},"
end
Output:
1,2,3, ,4,5,6, ,
"123 456 ".gsub(/(?<!\A)(?!\z)/, ",")
# => "1,2,3, ,4,5,6, "
sorry for bad English. Why Ruby quoting so strange? Or may be this is a bug?
irb(main):027:0> p eval "\" \+ \\+ \\\+ \\\\+ \\\\\+ \""
produces
=> " + + + \\+ \\+ "
or
irb(main):027:0> puts eval "\" \+ \\+ \\\+ \\\\+ \\\\\+ \""
produces
=> + + + \+ \+
or another example
irb(main):067:0> " \" " =~ Regexp.new(eval("\" \\\" \""))
=> 0
irb(main):068:0> " + " =~ Regexp.new(eval("\" \\\\+ \""))
=> 0
When you write \" \+ \\+ \\\+ \\\\+ \" you get " + \+ \+ \\+ ". After, you use eval to execute this string, that contains another double-quoted string. You get, then, + + + \+.
\\ => \
\x => x (se não for nenhum caso especial, como \n)
ruby escaping is perfectly good,
eval = evaluate/execute the string