gsub escaped double quote to an escaped single quote in string - ruby

I have the following input string:
string = "\"Newegg.com\" <Promo#email.newegg.com>"
I want to replace the \" with \'. I tried this:
string.gsub(/\"/) {|i| "\\'" }
# => "\\'Newegg.com\\' <Promo#email.newegg.com>"
string.gsub(/\"/,%q(\\\'))
# => "\\'Newegg.com\\' <Promo#email.newegg.com>"
In both ways, it actually has two instances of \, but I want only one. It seems to be an issue with the backslash and escaping b/c this works otherwise:
string.gsub(/\"/,%q('))
# => "'Newegg.com' <Promo#email.newegg.com>"
-- Update 1--
yes, puts does display the "correct" value
temp = string.gsub(/\"/,%q(\\\'))
# => "\\'Newegg.com\\' <Promo#email.newegg.com>"
puts temp
# >> \'Newegg.com\' <Promo#email.newegg.com>
but I want to store this exact value displayed on the last line.

Your actual string doesn't include \
puts "\"Newegg.com\" <Promo#email.newegg.com>"
> "Newegg.com" <Promo#email.newegg.com>
This will replace " with ' as you wished:
puts "\"Newegg.com\" <Promo#email.newegg.com>".gsub('"', "'")
> 'Newegg.com' <Promo#email.newegg.com>
If you really wanted \", try another escape character like:
puts "\\\"Newegg.com\\\" <Promo#email.newegg.com>"
> \"Newegg.com\" <Promo#email.newegg.com>
Same replace should work:
puts "\\\"Newegg.com\\\" <Promo#email.newegg.com>".gsub('"', "'")
> \'Newegg.com\' <Promo#email.newegg.com>

Looks like your getting a bit confused (understandably so) by the returned result.
Keep in mind that in irb, the last result is formatted using .inspect, which means that it wraps strings in double quotes, and then escapes characters (backslashes and double quotes)' that would need to be escaped in a double quoted string. This is to distinguish between strings and other values such as numbers, arrays, hashes, etc.
However, that is just the result of inspect. if you use puts to output the value, it will output it without any escaping - it is a more accurate representation of your value.The value displayed by puts is the real value, and what would be stored if you saved the value to a variable.
If you still can't tell what your string looks like, try this:
temp = string.gsub(/\"/,%q(\\\'))
temp.split('')
=> ["\\", "'", "N", "e", "w", "e", "g", "g", ".", "c", "o", "m", "\\", "'", " ", "<", "P", "r", "o", "m", "o", "#", "e", "m", "a", "i", "l", ".", "n", "e", "w", "e", "g", "g", ".", "c", "o", "m", ">"]
This explodes your string into an array of single characters, and can make it easier to see exactly what is in your string. Notice you have a \ character (displayed as "\\", but since each string is guaranteed to be exactly one character long, you know it is being displayed that way because of inspect) and a ' character at the beginning.

Related

Why the Ruby each iterator goes first in the execution?

I've came across a weird thing doing simple tasks in Ruby. I just want to iterate the alphabet with the each method but the iteration goes first in the execution:
alfawit = ("a".."z")
puts "That's an alphabet: \n\n #{ alfawit.each { |litera| puts litera } } "
and this code results in this: (abbreviated)
a
b
c
⋮
x
y
z
That's an alphabet:
a..z
Any ideas why it works like this or what supposedly I did wrong?
Thanks in advance.
Because your each call is interpolated in your string literal that's executed before the fixed string. Also, each returns an Enumerable, in fact you print even that. Try this one
alfawit = ("a".."z")
puts "That's an alphabet: \n\n"
alfawit.each { |litera| puts litera }
or
puts "That's an alphabet: \n\n"
("a".."z").each { |litera| puts litera }
you can use interpolation if you want but in this way
alfawit = ("a".."z")
puts "That's an alphabet: \n\n#{alfawit.to_a.join("\n")}"
You can easily see what's going on if you extract the interpolation part into a variable:
alfawit = ("a".."z")
foo = alfawit.each { |litera| puts litera }
puts "That's an alphabet: \n\n #{ foo } "
The second line is causing the trouble: each invokes the block for each element of the range and then returns the receiver, so that foo becomes alfawit.
Here's another way to get the desired result:
alfawit = "a".."z"
puts "That's an alphabet:", alfawit.to_a
puts outputs each argument on a new line, but for array arguments, it outputs each element on a new line. Result:
That's an alphabet:
a
b
c
⋮
x
y
z
Likewise, you can turn the range into an argument list via *:
alfawit = "a".."z"
puts "That's an alphabet:", *alfawit
That's equivalent to:
puts "That's an alphabet:", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"

Regex to check alphanumeric string in ruby

I am trying to validate strings in ruby.
Any string which contains spaces,under scores or any special char should fail validation.
The valid string should contain only chars a-zA-Z0-9
My code looks like.
def validate(string)
regex ="/[^a-zA-Z0-9]$/
if(string =~ regex)
return "true"
else
return "false"
end
I am getting error:
TypeError: type mismatch: String given.
Can anyone please let me know what is the correct way of doing this?
If you are validating a line:
def validate(string)
!string.match(/\A[a-zA-Z0-9]*\z/).nil?
end
No need for return on each.
You can just check if a special character is present in the string.
def validate str
chars = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a
str.chars.detect {|ch| !chars.include?(ch)}.nil?
end
Result:
irb(main):005:0> validate "hello"
=> true
irb(main):006:0> validate "_90 "
=> false
def alpha_numeric?(char)
if (char =~ /[[:alpha:]]/ || char =~ /[[:digit:]]/)
true
else
false
end
end
OR
def alpha_numeric?(char)
if (char =~ /[[:alnum:]]/)
true
else
false
end
end
We are using regular expressions that match letters & digits:
The above [[:alpha:]] ,[[:digit:]] and [[:alnum:]] are POSIX bracket expressions, and they have the advantage of matching Unicode characters in their category. Hope this helps.
checkout the link below for more options:
Ruby: How to find out if a character is a letter or a digit?
No regex:
def validate(str)
str.count("^a-zA-Z0-9").zero? # ^ means "not"
end
Great answers above but just FYI, your error message is because you started your regex with a double quote ". You'll notice you have an odd number (5) of double quotes in your method.
Additionally, it's likely you want to return true and false as values rather than as quoted strings.
Similar to the very efficient regex-ish approach mentioned already by #steenslag and nearly just as fast:
str.tr("a-zA-Z0-9", "").length.zero?
OR
str.tr("a-zA-Z0-9", "") == 0
One benefit of using tr though is that you could also optionally analyze the results using the same basic formula:
str = "ABCxyz*123$"
rejected_chars = str.tr("a-zA-Z0-9", "")
#=> *$
is_valid = rejected_chars.length.zero?
#=> false
Similar to #rohit89:
VALID_CHARS = [*?a..?z, *?A..?Z, *'0'..'9']
#=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
# "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
# "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
# "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
# "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
def all_valid_chars?(str)
a = str.chars
a == a & VALID_CHARS
end
all_valid_chars?('a9Z3') #=> true
all_valid_chars?('a9 Z3') #=> false
Use .match? in Ruby 2.4+.
Ruby 2.4 introduced a convenient boolean-returning .match? method.
In your case, I would do something like this:
# Checks for any characters other than letters and numbers.
# Returns true if there are none. Returns false if there are one or more.
#
def valid?( string )
!string.match?( /[^a-zA-Z0-9]/ ) # NOTE: ^ inside [] set turns it into a negated set.
end

How to break down a string that's in an array even further

I'm trying to break down a sentence that's part of one string, but break it down into letters in their own array and have that inside one big array.
So what I mean is:
def break("hello world")
the code in the method would than result in this:
[["h","e","l","l","o], ["w","o","r","l","d"]]
The reason why I need it like that is so I can rearrange the letters in the order I want later. I've tried several things, but no luck.
"hello world".split.map &:chars
# => [["h", "e", "l", "l", "o"], ["w", "o", "r", "l", "d"]]
I wouldn't use break as a method name. It's a key word in the language.
def break_it(str)
str.split.map { |word| word.each_char.to_a }
end
break_it("hello world")

Extracting all but a certain phrase using regular expressions

I have a string that I want to extract all but a certain pattern into another variable.
first_string = "Q13 Hello, World!"
I'd like to get the Hello, World! out of the string and into another variable so that: second_string = "Hello, World!".
I attempted to create a regex that extracts all but the "Q13" and it works on Rubular but not in the console.
> first_string = "Q13 Hello, World!"
> second_string = first_string.scan(/[^(Q[0-9]{1,})]/)
=> [" ", "H", "e", "l", "l", "o", ",", " ", "W", "o", "r", "l", "d", "!"]
> second_string.join()
=> " Hello World!"
This is fine but I can't lose the leading space using the regex. That wouldn't be a problem except I have some application specific caveats...
Not all strings will have "Q13"... the "Q" will be there but the number will change. I don't know if "Q13" will come at the beginning or end of the text. I can't be certain what text will be in the string.
I can't rely on the leading space being there. It might also be a trailing space.
Any ideas?
Assuming you want to omit the Q[number] and any surrounding whitespace:
second_string = first_string.gsub(/\s?Q\d+\s?/, "")
If you want to omit the Q[number] but not the surrounding whitespace:
second_string = first_string.gsub(/Q\d+/, "")
Try this:
second_string = first_string.scan(/\A(?:Q[0-9]+)?(?: )?(.*?)(?: )?(?:Q[0-9]+)?\z/).flatten.first
Live test in Ruby console
2.0.0p247 :001 > first_string = "Q12 Hello World! Q87"
=> "Q12 Hello World! Q87"
2.0.0p247 :002 > second_string = first_string.scan(/\A(?:Q[0-9]+)?(?: )?(.*?)(?: )?(?:Q[0-9]+)?\z/).flatten.first
=> "Hello World!"

Is there a one liner to destructively use `.split(//)` (e.g. turn string into array)?

So far I have:
my_array = "Foo bar na nas"
my_array.delete!(" ").downcase!
my_array = my_array.split(//).uniq
To get:
==> ["f", "o", "b", "a", "r", "n", "s"]
I can't seem to use .split!(//) like .delete! or .downcase! but I want to do all of this in one step. Is it possible?
Using my_array.delete!(" ").downcase!.split!(//) yields "': undefined method 'split!' for nil:NilClass" so I assume .split! just doesn't exist.
No. If you will read documentation you will get that destructive methods return nil when there is nothing to change, so you cannot chain them. If you want to change string to array of it's letters excluding whitespces you should rathe run:
my_array = "Foo bar na nas".downcase.gsub(/\W/, '').split(//).uniq
There also don't exist destructive method split!. Just how can it exist? Ruby is strong-typed language so you cannot change String into Array because they aren't related.
my_array.downcase.gsub(' ','').chars.uniq
Why not use split with a regular expression matching white space or nothing?
"Foo bar na nas".downcase.split(/\s*/).uniq
This returns
["f", "o", "b", "a", "r", "n", "s"]
split! does not exist because by convention methods with ! alter the object itself in ruby, and you can not coerce a string into an array because ruby is strongly typed.
"Foo bar na nas".downcase.split(//).uniq.keep_if { |item| item != " " }
#=> ["f", "o", "b", "a", "r", "n", "s"]
"Foo bar na nas t p".downcase.split(//).uniq.keep_if { |item| item != " " }
#=> ["f", "o", "b", "a", "r", "n", "s", "t", "p"]

Resources