How to remove backslashes in ruby strings - ruby

In ruby, I am trying to convert
'\"\"'
to
'""'
In short, what's the cleanest way to remove the backslashes?

You can use the gsub method on any string to remove unwanted characters.
some_string.gsub('\\"', '"')

Yet another:
'\"\"'.delete("\\") # => "\"\""

Use String#tr
s = '\"\"'
s.tr('\\', '') # => "\"\""

Related

How to implement %% to split string like shell in ruby

I am new to ruby and I want to do the following action to remove last "_val3" in ruby:
$ val="val1_val2_val3"
$ echo ${val%_*}
val1_val2
I used to use echo ${val%_*} to get "val1_val2", but i do not how do this in ruby.
Also, how to get "val1"?
Is there a good way to do them?
Not a ruby expert but I'll get the ball rolling with a regular expression:
a.sub /_[^_]*$/, ''
Match an underscore followed by any number of non-underscores at the end of the string. Replace with nothing.
You can use a single gsub to get your expected o/p,
a = "a-b_c_d"
# => "a-b_c_d"
a.gsub /_[a-z]*$/, ''
# => "a-b_c"
Or, you can use ruby split and join,
a.split("_")[0..-2].join("_")
# => "a-b_c"
String#rpartition would probably work:
'a-b_c_d'.rpartition('_') #=> ["a-b_c", "_", "d"]
rpartition looks for the last '_' and returns an array containing the part before it, the separator itself and the part after it.

How do I remove backslashes from a JSON string?

I have a JSON string that looks as below
'{\"test\":{\"test1\":{\"test1\":[{\"test2\":\"1\",\"test3\": \"foo\",\"test4\":\"bar\",\"test5\":\"test7\"}]}}}'
I need to change it to the one below using Ruby or Rails:
'{"test":{"test1":{"test1":[{"test2":"1","test3": "foo","test4":"bar","test5":"bar2"}]}}}'
I need to know how to remove those slashes.
To avoid generating JSON with backslashes in console, use puts:
> hash = {test: 'test'}
=> {:test=>"test"}
> hash.to_json
=> "{\"test\":\"test\"}"
> puts hash.to_json
{"test":"test"}
You could also use JSON.pretty_generate, with puts of course.
> puts JSON.pretty_generate(hash)
{
"test": "test"
}
Use Ruby's String#delete! method. For example:
str = '{\"test\":{\"test1\":{\"test1\":[{\"test2\":\"1\",\"test3\": \"foo\",\"test4\":\"bar\",\"test5\":\"test7\"}]}}}'
str.delete! '\\'
puts str
#=> {"test":{"test1":{"test1":[{"test2":"1","test3": "foo","test4":"bar","test5":"test7"}]}}}
Replace all backslashes with empty string using gsub:
json.gsub('\\', '')
Note that the default output in a REPL uses inspect, which will double-quote the string and still include backslashes to escape the double-quotes. Use puts to see the string’s exact contents:
{"test":{"test1":{"test1":[{"test2":"1","test3": "foo","test4":"bar","test5":"test7"}]}}}
Further, note that this will remove all backslashes, and makes no regard for their context. You may wish to only remove backslashes preceding a double-quote, in which case you can do:
json.gsub('\"', '')
I needed to print a pretty JSON array to a file. I created an array of JSON objects then needed to print to a file for the DBA to manipulate.
This is how i did it.
puts(((dirtyData.gsub(/\\"/, "\"")).gsub(/\["/, "\[")).gsub(/"\]/, "\]"))
It's a triple nested gsub that removes the \" first then removes the [" lastly removes the "]
I hope this helps
I tried the earlier approaches and they did not seem to fix my issue. My json still had backslashes. However, I found a fix to solve this issue.
myuglycode.gsub!(/\"/, '\'')
Use JSON.parse()
JSON.parse("{\"test\":{\"test1\":{\"test1\":[{\"test2\":\"1\",\"test3\": \"foo\",\"test4\":\"bar\",\"test5\":\"test7\"}]}}}")
> {"test"=>{"test1"=>{"test1"=>[{"test2"=>"1", "test3"=>"foo", "test4"=>"bar", "test5"=>"test7"}]}}}
Note that the "json-string" must me double-quoted for this to work, otherwise \" would be read as is instead of being "translated" to " which return a JSON::ParserError Exception.

Replacing regex capture with the same capture and an extra string

I am trying to escape certain characters in a string. In particular, I want to turn
abc/def.ghi into abc\/def\.ghi
I tried to use the following syntax:
1.9.3p125 :076 > "abc/def.ghi".gsub(/([\/.])/, '\\\1')
=> "abc\\1def\\1ghi"
Hmm. This behaves as if capture replacements didn't work. Yet, when I tried this:
1.9.3p125 :075 > "abc/def.ghi".gsub(/([\/.])/, '\1')
=> "abc/def.ghi"
... I got the replacement to work, but, of course, my prefixes weren't part of it.
What is the correct syntax to do something like this?
This should be easier
gsub(/(?=[.\/])/, "\\")
If you are trying to prepare a string to be used as a regex pattern, use the right tool:
Regexp.escape('abc/def.ghi')
=> "abc/def\\.ghi"
You can then use the resulting string to create a regex:
/#{ Regexp.escape('abc/def.ghi') }/
=> /abc\/def\.ghi/
or:
Regexp.new(Regexp.escape('abc/def.ghi'))
=> /abc\/def\.ghi/
From the docs:
Escapes any characters that would have special meaning in a regular expression. Returns a new escaped string, or self if no characters are escaped. For any string, Regexp.new(Regexp.escape(str))=~str will be true.
Regexp.escape('\*?{}.') #=> \\\*\?\{\}\.
You can pass a block to gsub:
>> "abc/def.ghi".gsub(/([\/.])/) {|m| "\\#{m}"}
=> "abc\\/def\\.ghi"
Not nearly as elegant as #sawa's answer, but it was the only way I could find to get it to work if you need the replacing string to contain the captured group/backreference (rather than inserting the replacement before the look-ahead).

How to strip leading and trailing quote from string, in Ruby

I want to strip leading and trailing quotes, in Ruby, from a string. The quote character will occur 0 or 1 time. For example, all of the following should be converted to foo,bar:
"foo,bar"
"foo,bar
foo,bar"
foo,bar
You could also use the chomp function, but it unfortunately only works in the end of the string, assuming there was a reverse chomp, you could:
'"foo,bar"'.rchomp('"').chomp('"')
Implementing rchomp is straightforward:
class String
def rchomp(sep = $/)
self.start_with?(sep) ? self[sep.size..-1] : self
end
end
Note that you could also do it inline, with the slightly less efficient version:
'"foo,bar"'.chomp('"').reverse.chomp('"').reverse
EDIT: Since Ruby 2.5, rchomp(x) is available under the name delete_prefix, and chomp(x) is available as delete_suffix, meaning that you can use
'"foo,bar"'.delete_prefix('"').delete_suffix('"')
I can use gsub to search for the leading or trailing quote and replace it with an empty string:
s = "\"foo,bar\""
s.gsub!(/^\"|\"?$/, '')
As suggested by comments below, a better solution is:
s.gsub!(/\A"|"\Z/, '')
As usual everyone grabs regex from the toolbox first. :-)
As an alternate I'll recommend looking into .tr('"', '') (AKA "translate") which, in this use, is really stripping the quotes.
Another approach would be
remove_quotations('"foo,bar"')
def remove_quotations(str)
if str.start_with?('"')
str = str.slice(1..-1)
end
if str.end_with?('"')
str = str.slice(0..-2)
end
end
It is without RegExps and start_with?/end_with? are nicely readable.
It frustrates me that strip only works on whitespace. I need to strip all kinds of characters! Here's a String extension that will fix that:
class String
def trim sep=/\s/
sep_source = sep.is_a?(Regexp) ? sep.source : Regexp.escape(sep)
pattern = Regexp.new("\\A(#{sep_source})*(.*?)(#{sep_source})*\\z")
self[pattern, 2]
end
end
Output
'"foo,bar"'.trim '"' # => "foo,bar"
'"foo,bar'.trim '"' # => "foo,bar"
'foo,bar"'.trim '"' # => "foo,bar"
'foo,bar'.trim '"' # => "foo,bar"
' foo,bar'.trim # => "foo,bar"
'afoo,bare'.trim /[aeiou]/ # => "foo,bar"
Assuming that quotes can only appear at the beginning or end, you could just remove all quotes, without any custom method:
'"foo,bar"'.delete('"')
I wanted the same but for slashes in url path, which can be /test/test/test/ (so that it has the stripping characters in the middle) and eventually came up with something like this to avoid regexps:
'/test/test/test/'.split('/').reject(|i| i.empty?).join('/')
Which in this case translates obviously to:
'"foo,bar"'.split('"').select{|i| i != ""}.join('"')
or
'"foo,bar"'.split('"').reject{|i| i.empty?}.join('"')
Regexs can be pretty heavy and lead to some funky errors. If you are not dealing with massive strings and the data is pretty uniform you can use a simpler approach.
If you know the strings have starting and leading quotes you can splice the entire string:
string = "'This has quotes!'"
trimmed = string[1..-2]
puts trimmed # "This has quotes!"
This can also be turned into a simple function:
# In this case, 34 is \" and 39 is ', you can add other codes etc.
def trim_chars(string, char_codes=[34, 39])
if char_codes.include?(string[0]) && char_codes.include?(string[-1])
string[1..-2]
else
string
end
end
You can strip non-optional quotes with scan:
'"foo"bar"'.scan(/"(.*)"/)[0][0]
# => "foo\"bar"

Remove character from string if it starts with that character?

How can I remove the very first "1" from any string if that string starts with a "1"?
"1hello world" => "hello world"
"112345" => "12345"
I'm thinking of doing
string.sub!('1', '') if string =~ /^1/
but I' wondering there's a better way. Thanks!
Why not just include the regex in the sub! method?
string.sub!(/^1/, '')
As of Ruby 2.5 you can use delete_prefix or delete_prefix! to achieve this in a readable manner.
In this case "1hello world".delete_prefix("1").
More info here:
https://blog.jetbrains.com/ruby/2017/10/10-new-features-in-ruby-2-5/
https://bugs.ruby-lang.org/issues/12694
'invisible'.delete_prefix('in') #=> "visible"
'pink'.delete_prefix('in') #=> "pink"
N.B. you can also use this to remove items from the end of a string with delete_suffix and delete_suffix!
'worked'.delete_suffix('ed') #=> "work"
'medical'.delete_suffix('ed') #=> "medical"
https://bugs.ruby-lang.org/issues/13665
I've answered in a little more detail (with benchmarks) here: What is the easiest way to remove the first character from a string?
if you're going to use regex for the match, you may as well use it for the replacement
string.sub!(%r{^1},"")
BTW, the %r{} is just an alternate syntax for regular expressions. You can use %r followed by any character e.g. %r!^1!.
Careful using sub!(/^1/,'') ! In case the string doesn't match /^1/ it will return nil. You should probably use sub (without the bang).
This answer might be more optimised: What is the easiest way to remove the first character from a string?
string[0] = '' if string[0] == '1'
I'd like to post a tiny improvement to the otherwise excellent answer by Zach. The ^ matches the beginning of every line in Ruby regex. This means there can be multiple matches per string. Kenji asked about the beginning of the string which means they have to use this regex instead:
string.sub!(/\A1/, '')
Compare this - multiple matches with this - one match.

Resources