replace white space with ' \ ' in ruby to make them bash-readable - ruby

How can I format "hello bro" to obtain "hello\ bro" in ruby.
When I use "...".gsub /\s/,'\\ ', I obtain "hello\\ bro" which bash cannot read. The '\ ' replacement has no effect.
Thanks

Your gsub arguments are actually correct. If you're running it through irb, it may not be obvious though - backslashes are escaped in the console output. For instance:
irb(main):036:0> my_str = "hello bro".gsub /\s/, '\\ '
=> "hello\\ bro"
However, we'll see the expected string when we output the value of my_str:
irb(main):043:0> puts my_str
hello\ bro
That said, unless you're absolutely sure that spaces are the only characters you need to escape, you're better off using something like Shellwords, as mentioned in the comments.

Related

Replacing escape quotes with just quotes in a string

So I'm having an issue replacing \" in a string.
My Objective:
Given a string, if there's an escaped quote in the string, replace it with just a quote
So for example:
"hello\"74" would be "hello"74"
simp"\"sons would be simp"sons
jump98" would be jump98"
I'm currently trying this: but obviously that doesn't work and messes everything up, any assistance would be awesome
str.replace "\\"", "\""
I guess you are being mistaken by how \ works. You can never define a string as
a = "hello"74"
Also escape character is used only while defining the variable its not part of the value. Eg:
a = "hello\"74"
# => "hello\"74"
puts a
# hello"74
However in-case my above assumption is incorrect following example should help you:
a = 'hello\"74'
# => "hello\\\"74"
puts a
# hello\"74
a.gsub!("\\","")
# => "hello\"74"
puts a
# hello"74
EDIT
The above gsub will replace all instances of \ however OP needs only to replace '" with ". Following should do the trick:
a.gsub!("\\\"","\"")
# => "hello\"74"
puts a
# hello"74
You can use gsub:
word = 'simp"\"sons';
print word.gsub(/\\"/, '"');
//=> simp""sons
I'm currently trying str.replace "\\"", "\"" but obviously that doesn't work and messes everything up, any assistance would be awesome
str.replace "\\"", "\"" doesn't work for two reasons:
It's the wrong method. String#replace replaces the entire string, you are looking for String#gsub.
"\\"" is incorrect: " starts the string, \\ is a backslash (correctly escaped) and " ends the string. The last " starts a new string.
You have to either escape the double quote:
puts "\\\"" #=> \"
Or use single quotes:
puts '\\"' #=> \"
Example:
content = <<-EOF
"hello\"74"
simp"\"sons
jump98"
EOF
puts content.gsub('\\"', '"')
Output:
"hello"74"
simp""sons
jump98"

Escape spaces in a linux pathname with Ruby gsub

I am trying to escape the spaces in a Linux path. However, whenever I try to escape my backslash I end up with a double slash.
Example path:
/mnt/drive/site/usa/1201 East/1201 East Invoice.pdf
So that I can use this in Linux I want to escape it as:
/mnt/drive/site/usa/1201\ East/1201\ East\ Invoice.pdf
So I'm trying this:
backup_item.gsub("\s", "\\\s")
But I get an unexpected output of
/mnt/drive/site/usa/1201\\ East/1201\\ East\\ Invoice.pdf
Stefan is right; I just want to point out that if you have to escape strings for shell use you should check Shellwords::shellescape:
require 'shellwords'
puts Shellwords.shellescape "/mnt/drive/site/usa/1201 East/1201 East Invoice.pdf"
# prints /mnt/drive/site/usa/1201\ East/1201\ East\ Invoice.pdf
# or
puts "/mnt/drive/site/usa/1201 East/1201 East Invoice.pdf".shellescape
# prints /mnt/drive/site/usa/1201\ East/1201\ East\ Invoice.pdf
# or (as reported by #hagello)
puts shellwords.escape "/mnt/drive/site/usa/1201 East/1201 East Invoice.pdf"
# prints /mnt/drive/site/usa/1201\ East/1201\ East\ Invoice.pdf
That is the string's inspect value, "a printable version of str, surrounded by quote marks, with special characters escaped":
quoted = "path/to/file with spaces".gsub(/ /, '\ ')
=> "path/to/file\\ with\\ spaces"
Just print the string:
puts quoted
Output:
path/to/file\ with\ spaces

Backslashes in gsub (escaping and backreferencing)

Consider the following snippet:
puts 'hello'.gsub(/.+/, '\0 \\0 \\\0 \\\\0')
This prints (as seen on ideone.com):
hello hello \0 \0
This was very surprising, because I'd expect to see something like this instead:
hello \0 \hello \\0
My argument is that \ is an escape character, so you write \\ to get a literal backslash, thus \\0 is a literal backslash \ followed by 0, etc. Obviously this is not how gsub is interpreting it, so can someone explain what's going on?
And what do I have to do to get the replacement I want above?
Escaping is limited when using single quotes rather then double quotes:
puts 'sinlge\nquote'
puts "double\nquote"
"\0" is the null-character (used i.e. in C to determine the end of a string), where as '\0' is "\\0", therefore both 'hello'.gsub(/.+/, '\0') and 'hello'.gsub(/.+/, "\\0") return "hello", but 'hello'.gsub(/.+/, "\0") returns "\000". Now 'hello'.gsub(/.+/, '\\0') returning 'hello' is ruby trying to deal with programmers not keeping the difference between single and double quotes in mind. In fact, this has nothing to do with gsub: '\0' == "\\0" and '\\0' == "\\0". Following this logic, whatever you might think of it, this is how ruby sees the other strings: both '\\\0' and '\\\\0' equal "\\\\0", which (when printed) gives you \\0. As gsub uses \x for inserting match number x, you need a way to escape \x, which is \\x, or in its string representation: "\\\\x".
Therefore the line
puts 'hello'.gsub(/.+/, "\\0 \\\\0 \\\\\\0 \\\\\\\\0")
indeed results in
hello \0 \hello \\0

How to add a single backslash character to a string in Ruby?

I want to insert backslash before apostrophe in "children's world" string. Is there a easy way to do it?
irb(main):035:0> s = "children's world"
=> "children's world"
irb(main):036:0> s.gsub('\'', '\\\'')
=> "childrens worlds world"
Answer
You need some extra backslashes:
>> puts "children's world".gsub("'", '\\\\\'')
children\'s world
or slightly more concisely (since you don't need to escape the ' in a double-quoted string):
>> puts "children's world".gsub("'", "\\\\'")
children\'s world
or even more concisely:
>> puts "children's world".gsub("'") { "\\'" }
children\'s world
Explanation
Your '\\\'' generates \' as a string:
>> puts '\\\''
\'
and \' is a special replacement pattern in Ruby. From ruby-doc.org:
you may refer to some special match variables using these combinations ... \' corresponds to $', which contains string after match
So the \' that gsub sees in the second argument is being interpreted as a special pattern (everything in the original string after the match) instead of as a literal \'.
So what you want gsub to see is actually \\', which can be produced by '\\\\\'' or "\\\\'".
Or, if you use the block form of gsub (gsub("xxx") { "yyy" }) then Ruby takes the replacement string "yyy" literally without trying to apply replacement patterns.
Note: If you have to create a replacement string with a lot of \s you could take advantage of the fact that when you use /.../ (or %r{...}) you don't have to double-escape the backslashes:
>> puts "children's world".gsub("'", /\\'/.source)
children\'s world
Or you could use a single-quoted heredoc: (using <<'STR' instead of just <<STR)
>> puts "children's world".gsub("'", <<'STR'.strip)
\\'
STR
children\'s world
>> puts s.gsub("'", "\\\\'")
children\'s world
Your problem is that the string "\'" is meaningful to gsub in a replacement string. In order to make it work the way you want, you have to use the block form.
s.gsub("'") {"\\'"}

How to replace multiple newlines in a row with one newline using Ruby

I have a script written in ruby. I need to remove any duplicate newlines (e.g.)
\n
\n
\n
to
\n
My current attempt worked (or rather not) using
str.gsub!(/\n\n/, "\n")
Which gave me no change to the output. What am I doing wrong?
This works for me:
#!/usr/bin/ruby
$s = "foo\n\n\nbar\nbaz\n\n\nquux";
puts $s
$s.gsub!(/[\n]+/, "\n");
puts $s
Use the more idiomatic String#squeeze instead of gsub.
str = "a\n\n\nb\n\n\n\n\n\nc"
str.squeeze("\n") # => "a\nb\nc"
You need to match more than one newline up to an infinite amount. Your code example will work with just a minor tweak:
str.gsub!(/\n+/, "\n")
For example:
str = "this\n\n\nis\n\n\n\n\na\ntest"
str.gsub!(/\n+/, "\n") # => "this\nis\na\ntest"
are you sure it shouldn't be /\n\n\n/, "\n" that what you seem to be wanting in your question above.
also, are you sure it's not doing a windows new-line "\r\n"?
EDIT: Additional info
Per Comment
"The amount of newlines can change. Different lines have between 2 and 5 newlines."
if you only want to hit the 2-5 lines try this
/\n{2,5}/, "\n"
Simply splitting and recombining the lines will give the desired result
>> "one\ntwo\n\nthree\n".split.join("\n")
=> "one\ntwo\nthree"
Edit: I just noticed this will replace ALL whitespace substrings with newlines, e.g.
>> "one two three\n".split.join("\n")
=> "one\ntwo\nthree"
First check that this is what you want!
Simply calling split will also trim out all of your whitespace.
You need to pass \n to split
>> "one ok \ntwo\n\nthree\n".split(/\n+/).join("\n")
=> "one ok \ntwo\nthree"
Additionally, also works with
spaces on blank lines
n number of back to back blank lines
str.gsub! /\n^\s*\n/, "\n\n"
where,
\n is of course newline
\s is space
denotes 1 or more spaces along when used after \s
Try This It Worked for me:
s = test\n\n\nbar\n\n\nfooo
s.gsub("\n\n", '')
Ruby needs the backslashes escaped differently than you have provided.
str.sub!("\\\\n+\\\\n","\\\\n")
http://www.ruby-forum.com/topic/176239

Resources