Why does this evaluate to false? "S" == /[S]/ => 0 - ruby

I'm a ruby newbie and I'm having trouble understanding why "S" == /[S]/ evaluates to false.
Can anyone explain this? I've also tried
"S" =~ /[S]/
#=> 0 `
"S" =~ /[^S]/
#=> nil
baffling to me

"S" == /[S]/ is false because == in Ruby doesn't evaluate whether a regexp matches, it just determines whether two objects are equal. The string "S" and the regexp /[S]/ are of course completely different objects and not equal.
=~ (which is a correct way to match a regexp against a string in Ruby) returns the match position. In your first example the match position is the beginning of the string, 0. In the second example there is no match, so =~ returns nil.

"S" == /[S]/
Everything (almost) in Ruby is an object. In this case you are checking for equality between an instance of a String "S" and an instance of a Regexp /[S]/. Therefore, by definition, they are two different objects, hence the expression returns false. Rather than checking for equality with == you should use =~
"S" == /[S]/
When you use a match operator =~ it returns the index of the first match found in a string. Remember that indexing in Ruby starts from 0. In your example the first character in the provided string is matched. The first character is indexed with 0 and that is what the statement returns.
"S" == /[^S]/
By using a caret ^ you are telling Ruby to match anything but what is between square brackets (this is only true in square brackets, ^ is also used to indicate the beginning of a string if used outside []). In your case it is anything but S. Ruby does not find a match and returns nil.

Related

Ruby, True/false regex

So I've got an issue where my regex looks like this: /true|false/.
When I check the word falsee I get a true from this regex, is there a way to just limit it to the exact true or false words?
Use this regex:
/^(true|false)$/
It will match the beginning and end of the test string with ^ and $, respectively, so nothing else can be in the string (exact match).
See live example at Regex101.
UPDATE (see #w0lf's comment): The parentheses are to isolate the true|false clause so that they are not grouped incorrectly. (This also puts the true or false match in the first capturing group, but since it seems that you are only matching and not capturing an output, this should not make a difference).
Alternatively, if you simply want to match two values, there are easier ways in Ruby. #SimoneCarletti suggests one. You can also use the basic == or eql? operators. Try running the following script to see that these all work:
values = ["true", "false", "almosttrue", "falsealmost"]
values.each do | value |
puts value
# these three are all equivalent
puts "match with if" if value == "true" || value == "false"
puts "match with equals?" if (value.eql? "true") || (value.eql? "false")
puts "match with regex" if /^(true|false)$/.match value
puts
end
You need to use the ^ and $ anchors:
/^(true|false)$/
Edit: As Cary pointed out in the comments, the pattern above will also match multiline strings that happen to contain a line with true or false. To avoid this, use the \A and \z delimiters that match the beginning and end of string respectively:
/\A(true|false)\z/
Try out
/^(true|false)$/
where ^ is the start of a line and $ the end.
You can use
/^(true|false)$/
or even better
/\A(true|false)\z/
that will match the beginning and end of the string (instead of line). If you only need to match for whose words, it may be more efficient to use a simple array and include?:
%w( true false ).include?(value)

Ruby: =~ symbol - what does it mean [duplicate]

I saw this on a screencast and couldn't figure out what it was. Reference sheets just pile it in with other operators as a general pattern match operator.
It matches string to a regular expression.
'hello' =~ /^h/ # => 0
If there is no match, it will return nil. If you pass it invalid arguments (ie, left or right-hand sides are not correct), it will either throw a TypeError or return false.
From ruby-doc :
str =~ obj => fixnum or nil
Match—If obj is a Regexp, use it as a pattern to match against str, and returns the offset position the match starts, or nil if there is no match. Otherwise, invokes obj.=~, passing str as an argument. The default =~ in Object returns false.
"cat o' 9 tails" =~ /\d/ #=> 7
"cat o' 9 tails" =~ 9 #=> false
Well, the reference is correct, it is the "matches this regex" operator.
if var =~ /myregex/ then something end
As the other answers already stated, =~ is the regular expression vs string match operator.
Note: The =~ operator is not commutative
Please consider the note below from the ruby doc site, as I have seen yet only the first form
str =~ regexp
used in the other answers:
Note: str =~ regexp is not the same as regexp =~ str. Strings captured
from named capture groups are assigned to local variables only in the
second case.
Here is the documentation for the second form: link
Regular expression string matching. Here's a detailed list of operators: http://phrogz.net/programmingruby/tut_expressions.html#table_7.1
Regular expression string matching:
puts true if url =~ /google.com/
You can read '=~' as 'is matching'.
I believe this is a pattern matching operator used with regex.

Test if a regexp does not match the beginning of a string without using .nil?

I'm testing some strings to make sure they start with a letter:
name =~ /\A[a-zA-Z].*/
but since in Ruby this evaluates to either nil or 0 and both cast to false, I need to put an additional .nil? test:
if(name =~ /\A[a-zA-Z].*/).nil? ...
Is this the proper way or am I missing something?
EDIT:
Thanks for the replies, in my ignorance I made wrong assumptions, oversimplified the example. It should read (note the negation):
name !=~ /\A[a-zA-Z].*/
irb(main):001:0> a = "abc"
=> "abc"
irb(main):006:0> (a !=~/\Aabc/)
=> true
irb(main):007:0> (a !=~/\Ab/)
=> true
but since in Ruby this evaluates to either nil or 0 and both cast to false
wrong, only nil (and false, to be precise) are treated as false in conditionals. 0 is treated as true. So
if name =~ /\A[a-zA-Z].*/
is perfectly ok.
About your edited question, you're not allowed to add exclamation sign (!) to any operator to make it negated operator. There's no such operator (BTW, these 'operators' are actually methods) as !=~, so to achieve your goal. you should do:
if !(name =~ /\A[a-zA-Z].*/)
or you can use unless instead:
unless name =~ /\A[a-zA-Z].*/

Ruby regexp returning "" vs nil

What is the reason behind different results between the following regexp statements:
"abbcccddddeeee"[/z*/] # => ""
And these that return nil:
"some matching content"[/missing/] # => nil
"start end"[/\Aend/] # => nil
What's happening is that /z*/ will return zero or more occurrences of z.
If you use /z+/, which returns one or more, you'll see it returns nil as expected.
The regular expression /z*/ matches 0 or more z characters, so it also matches an empty string at the beginning of your string. Consider this:
"abbcccddddeeee" =~ /z*/
# => 0
Thus String#[] returns the matched empty string.
In your second example the expressions /missing/ and /\Aend/ don't match anything so nil is returned.
* wild-card stands for 0 or more matches so even if your z is not present it will show a empty string match. on the other hand you can use + for 1 or more and ? for zero or more matches.

What is the "=~" operator in Ruby?

I saw this on a screencast and couldn't figure out what it was. Reference sheets just pile it in with other operators as a general pattern match operator.
It matches string to a regular expression.
'hello' =~ /^h/ # => 0
If there is no match, it will return nil. If you pass it invalid arguments (ie, left or right-hand sides are not correct), it will either throw a TypeError or return false.
From ruby-doc :
str =~ obj => fixnum or nil
Match—If obj is a Regexp, use it as a pattern to match against str, and returns the offset position the match starts, or nil if there is no match. Otherwise, invokes obj.=~, passing str as an argument. The default =~ in Object returns false.
"cat o' 9 tails" =~ /\d/ #=> 7
"cat o' 9 tails" =~ 9 #=> false
Well, the reference is correct, it is the "matches this regex" operator.
if var =~ /myregex/ then something end
As the other answers already stated, =~ is the regular expression vs string match operator.
Note: The =~ operator is not commutative
Please consider the note below from the ruby doc site, as I have seen yet only the first form
str =~ regexp
used in the other answers:
Note: str =~ regexp is not the same as regexp =~ str. Strings captured
from named capture groups are assigned to local variables only in the
second case.
Here is the documentation for the second form: link
Regular expression string matching. Here's a detailed list of operators: http://phrogz.net/programmingruby/tut_expressions.html#table_7.1
Regular expression string matching:
puts true if url =~ /google.com/
You can read '=~' as 'is matching'.
I believe this is a pattern matching operator used with regex.

Resources