How come you can't gsub this string in Ruby? - ruby

These \\n are showing up in my strings even though it should only be \n.
But if I do this :
"\n".gsub('\\n','\b')
It returns :
"\n"
Ideally, I'm trying to find a regex that could rewrite this string :
"R3pQvDqmz/EQ7zho2mhIeE6UB4dLa6GUH7173VEMdGCcdsRm5pernkqCgbnj\\nZjTX\\n"
To not display two backslashes, but just one like this :
"R3pQvDqmz/EQ7zho2mhIeE6UB4dLa6GUH7173VEMdGCcdsRm5pernkqCgbnj\nZjTX\n"
But any of the regex I do will not work. I can gsub out the \n and put something like X there, but if I put a \ in it, then Ruby escapes it with an additional \ which consequentially destroys my encryption module as it needs to be specific.
Any ideas?

You are falling into the trap of a different meaning of escapes when used in strings with double quotes vs single quotes. Double-quoted strings allow escape characters to be used. Thus, here "\n" actually is a one-character string containing a single line feed. Compare that to '\n' which is a two-character string containing a literal backslash followed by a character n.
This explains, whey your gsub doesn't match. If you use the following code, it should work:
"\\n".gsub('\n','\b')
For your actual issue, you can use this
string = "R3pQvDqmz/EQ7zho2mhIeE6UB4dLa6GUH7173VEMdGCcdsRm5pernkqCgbnj\\nZjTX\\n"
new_string = string.gsub("\\n", "\n")

Related

ruby gsub new line characters

I have a string with newline characters that I want to gsub out for white space.
"hello I\r\nam a test\r\n\r\nstring".gsub(/[\\r\\n]/, ' ')
something like this ^ only my regex seems to be replacing the 'r' and 'n' letters as well. the other constraint is sometimes the pattern repeats itself twice and thus would be replaced with two whitespaces in a row, although this is not preferable it is better than all the text being cut apart.
If there is a way to only select the new line characters. Or even better if there a more rubiestic way of approaching this outside of going to regex?
If you have mixed consecutive line breaks that you want to replace with a single space, you may use the following regex solution:
s.gsub(/\R+/, ' ')
See the Ruby demo.
The \R matches any type of line break and + matches one or more occurrences of the quantified subpattern.
Note that in case you have to deal with an older version of Ruby, you will need to use the negated character class [\r\n] that matches either \r or \n:
.gsub(/[\r\n]+/, ' ')
or - add all possible linebreaks:
/gsub(/(?:\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029])+/, ' ')
This should work for your test case:
"hello I\r\nam a test\r\n\r\nstring".gsub(/[\r\n]/, ' ')
If you don't want successive \r\n characters to result in duplicate spaces you can use this instead:
"hello I\r\nam a test\r\n\r\nstring".gsub(/[\r\n]+/, ' ')
(Note the addition of the + after the character class.)
As Wiktor mentioned, you're using \\ in your regex, which inside the regex literal /.../ actually escapes a backslash, meaning you're matching a literal backslash \, r, or n as part of your expression. Escaping characters works differently in regex literals, since \ is used so much, it makes no sense to have a special escape for it (as opposed to regular strings, which is a whole different animal).

GSUB and Forward Slash usage in Ruby

I often see the gsub function being called with the pattern parameter enclosed in forward slashes. For example:
>> phrase = "*** and *** ran to the ###."
>> phrase.gsub(/\*\*\*/, "WOOF")
=> "WOOF and WOOF ran to the ###."
I thought maybe it had something to do with escaping asterisks, but using single quotes and double quotes works just as well:
>> phrase = "*** and *** ran to the ###."
>> phrase.gsub('***', "WOOF")
=> "WOOF and WOOF ran to the ###."
>> phrase.gsub("***", "WOOF")
=> "WOOF and WOOF ran to the ###."
Is it just convention to use forward slash? What am I missing?
Use forward slashes if you need to use regular expressions.
If you use a string argument with gsub, it will just do a plain character match.
In your example, you need backslashes to escape the asterisks when using a regular expression, because asterisks have a special meaning in regex (optionally match something any number of times). They are not necessary when using a string, because they are just matched exactly.
In your example, you probably don't need to use a regular expression, since it is a simple pattern. However, if you wanted to match *** only when it was at the beginning of a string (e.g. the first bunch in your example), then you would want to use a regex, for example:
phrase.gsub(/^\*{3}/, "WOOF")
For more information on regular expressions, see: http://www.regular-expressions.info/.
For more information on using regular expressions in Ruby, see: http://ruby-doc.org/core-2.2.0/Regexp.html.
To play with regular expressions as they work in Ruby, try: http://rubular.com/.
You are missing reading the documentation:
The pattern is typically a Regexp; if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. '\d' will match a backlash followed by ā€˜dā€™, instead of a digit.
http://ruby-doc.org/core-2.1.4/String.html#method-i-gsub
In other words, you can give a string or a regular expression. Regular expressions can be delimited several ways:
Regexps are created using the /.../ and %r{...} literals, and by the Regexp::new constructor.
http://ruby-doc.org/core-2.2.2/Regexp.html
The benefit of %r and of the alternate %r delimiters is you can usually find a delimiter that doesn't collide with characters in the pattern, which would force escaping them, as in your example.
* has to be escaped because it has special meaning in a regex, but in a string it does not.

split string by spaces properly accounting for quotes and backslashes (ruby)

I want to split a string (insecure foreign line, like exim_mainlog line) by spaces, but not by spaces that are inside of double quotes, and ignore if the quote is escaped by a backslash like \", and ignore the backslash if it is just escaped like \\. Without slow parsing the string manually with FSM.
Example line:
U=mailnull T="test \"quote\" and wild blackslash\\" P=esmtps
Should be split into:
["U=mailnull", "T=\"test \\\"quote\\\" and wild blackslash\\\"", "P=esmtps"]
(Btw, I think ruby should had method for such split.., sigh).
I think I found simple enough solution: input.scan(/(?:"(?:\\.|[^"])*"|[^" ])+/)

Ruby string with quotes for shell command args?

Hi I need to create string like this:
drawtext="fontfile=/Users/stpn/Documents/Video_Experiments/fonts/Trebuchet_MS.ttf:text='content':fontsize=100:fontcolor=red:y=h/2"
I want to do something like
str = Q%[drawtext="fontfile=/Users/stpn/Documents/Video_Experiments/fonts/Trebuchet_MS.ttf:text='content':fontsize=100:fontcolor=red:y=h/2"]
I am getting this:
=> "drawtext=\"fontfile=/Users/stpn/Documents/Video_Experiments/fonts/Trebuchet_MS.ttf:text='content':fontsize=100:fontcolor=red:y=h/2\""
The escape characters after equals sign in drawtext=" is what I want to get rid of.. How to achieve that?
The string is to be used in a command line args.
Like many languages, Ruby needs a way of delimiting a quoted quote, and the enclosing quotes.
What you're seeing is the escape character which is a way of saying literal quote instead of syntactic quote:
foo = 'test="test"'
# => "test=\"test\""
The escape character is only there because double-quotes are used by default when inspecting a string. It's stored internally as a single character, of course. You may also see these in other circumstances such as a CR+LF delimited file line:
"example_line\r\n"
The \r and \n here correspond with carriage-return and line-feed characters. There's several of these characters defined in ANSI C that have carried over into many languages including Ruby and JavaScript.
When you output a string those escape characters are not displayed:
puts foo
test="test"

Substitute ' with \' in double-quoted string

The task is simple - I have a string like "I don't know" and I want substitute ' with \' (I know that I don't have to escape single quotes). How can I do it?
Try using the block form, it should work in all versions of Ruby:
s.gsub(/'/) {"\\'"}
# => "I don\\'t know"
[Edit]
The reason is that the gsub method has special handling for backslash sequences in the replacement string which correspond to the special match variables. So you can use $' (and $1, etc.) directly in the substituted string by using the form \\' (and \\1, etc.) instead.
The block form of gsub doesn't have this behavior, so that's the workaround when you're trying to sub in a string that looks like a special backslash sequence.

Resources