Match newline `\n` in ruby regex - ruby

I'm trying to understand why the following returns false: (** I should have put "outputs 0" **)
puts "a\nb" =~ Regexp.new(Regexp.escape("a\nb"), Regexp::MULTILINE | Regexp::EXTENDED)
Perhaps someone could explain.
I am trying to generate a Regexp from a multi-line String that will match the String.
Thanks in advance

puts will always return nil.
Your code should work fine, albeit lengthy. =~ returns the position of the match which is 0.
You could also use:
"a\nb" =~ /a\sb/m
or
"a\nb" =~ /a\nb/m
Note: The m option isn't necessary in this example but demonstrates how it would be used without Regexp.new.

Probably, puts caused this
1.9.3-194 (main):0 > puts ("a\nb" =~ Regexp.new(Regexp.escape("a\nb"), Regexp::MULTILINE | Regexp::EXTENDED) )
0
=> nil
1.9.3-194 (main):0 > "a\nb" =~ Regexp.new(Regexp.escape("a\nb"), Regexp::MULTILINE | Regexp::EXTENDED)
=> 0

Related

how ruby if column less than 4 print column 3?

Im triying to use this code but not work
ruby -a -F';' -ne if $F[2]<4 'puts $F[3]' ppp.txt
this is my file
mmm;2;nsfnjd
sadjjasjnsd;6;gdhjsd
gsduhdssdj;3;gsdhjhjsd
what is doing worng Please help me
First of all, instead of treating Ruby like some kind of fancy Perl and writing scripts like that, let's expand it into the Ruby code equivalent for clarity:
$; = ';'
while gets
$F = $_.split
if $F[2]<4
puts $F[3]
end
end
Your original code doesn't work, it can't possibly work because it's not valid Ruby code, and further, you're not properly quoting it to pass through the -e evaluation term. Trying to run it I get:
-bash: 4: No such file or directory
You're also presuming the array is 1-indexed, but it's not. It's 0-indexed. Additionally Ruby treats integer values as completely different from strings, never equivalent, not auto-converted. As such you need to call .to_i to convert.
Here's a re-written program that does the job:
File.open(ARGV[0]) do |fi|
fi.readlines.each do |line|
parts = line.chomp.split(';')
if parts[1].to_i < 4
puts parts[2]
end
end
end
I solved with this
ruby -a -F';' -ne ' if $F[1] < "4" ;puts $F[2] end ' ppp.txt

Why this regular expression gets true in ruby?

I was started learning the regular expressions in ruby. In that I had one problem. The problem is the below regular expression does not work as expected.
/^[\s]*$/ -- This will match only if the input contains white spaces or the input contains empty.
For example,
str = "
abc
"
if str =~ /^[\s]*$/
puts "Condition is true"
else
puts "Condition is false"
end
My expectation is this condition will gets false. But it gets true. I don't know why ?
In sed or grep it will work as expected. But why it does not works in ruby.
The reason is that in Ruby regex, ^ and $ match the start/end of a line. Change to \A and \z and you will get a false result.
See this Ruby demo at Ideone. The /\A\s*\z/ will only match strings that are either empty or have whitespace symbols only.
As for \s, it is a synonym for [ \t\r\n\f], not just [ \t\n]. See this Ruby Character Class reference:
/\s/ - A whitespace character: /[ \t\r\n\f]/

How to check ARGF is empty or not in Ruby

I want to do with ARGF like this.
# file.rb
if ARGF.???
puts ARGF.read
else
puts "no redirect."
end
$ echo "Hello world" | ruby file.rb
Hello world
$ ruby file.rb
no redirect.
I need to do without waiting user input. I tried eof? or closed? doesn't help. Any ideas?
NOTE I was misunderstood ARGF. please see comments below.
Basically you'd examine #filename. One way to do this is:
if ARGF.filename != "-"
puts ARGF.read
else
puts "no redirect."
end
And this is the more complete form:
#!/usr/bin/env ruby
if ARGF.filename != "-" or (not STDIN.tty? and not STDIN.closed?)
puts ARGF.read
else
puts "No redirect."
end
Another:
#!/usr/bin/env ruby
if not STDIN.tty? and not STDIN.closed?
puts STDIN.read
else
puts "No redirect."
end
There might be a better way, but for me I needed to read the contents of a files being passed as arguments as well as having a files contents redirected to stdin.
my_executable
#!/usr/bin/env ruby
puts ARGF.pos.zero?
Then
$ my_executable file1.txt # passed as argument
#=> true
$ my_executable < file1.txt # redirected to stdin
#=> true
$ my_executable
#=> false
So I took all three currently suggested solutions:
p (not STDIN.tty? and not STDIN.closed?)
p ARGF.filename
p ARGF.pos
and saw that none of them actually works:
$ ruby temp.rb
false
"-"
36471287
$ ruby temp.rb temp.rb
false
"temp.rb"
0
$ echo 123 | ruby temp.rb
true
"-"
temp.rb:3:in `pos': Illegal seek # rb_io_tell - <STDIN> (Errno::ESPIPE)
from temp.rb:3:in `<main>'
because to assume the ability to call the ARGF.read you want to get false/true/true.
So I suppose you have to combine them:
!STDIN.tty? && !STDIN.closed? || ARGF.filename != ?-

Is there a bug in Ruby lookbehind assertions (1.9/2.0)?

Why doesn't the regex (?<=fo).* match foo (whereas (?<=f).* does)?
"foo" =~ /(?<=f).*/m => 1
"foo" =~ /(?<=fo).*/m => nil
This only seems to happen with singleline mode turned on (dot matches newline); without it, everything is OK:
"foo" =~ /(?<=f).*/ => 1
"foo" =~ /(?<=fo).*/ => 2
Tested on Ruby 1.9.3 and 2.0.0.
See it on Rubular
EDIT: Some more observations:
Adding an end-of-line anchor doesn't change anything:
"foo" =~ /(?<=fo).*$/m => nil
But together with a lazy quantifier, it "works":
"foo" =~ /(?<=fo).*?$/m => 2
EDIT: And some more observations:
.+ works as does its equivalent {1,}, but only in Ruby 1.9 (it seems that that's the only behavioral difference between the two in this scenario):
"foo" =~ /(?<=fo).+/m => 2
"foo" =~ /(?<=fo).{1,}/ => 2
In Ruby 2.0:
"foo" =~ /(?<=fo).+/m => nil
"foo" =~ /(?<=fo).{1,}/m => nil
.{0,} is busted (in both 1.9 and 2.0):
"foo" =~ /(?<=fo).{0,}/m => nil
But {n,m} works in both:
"foo" =~ /(?<=fo).{0,1}/m => 2
"foo" =~ /(?<=fo).{0,2}/m => 2
"foo" =~ /(?<=fo).{0,999}/m => 2
"foo" =~ /(?<=fo).{1,999}/m => 2
This has been officially classified as a bug and subsequently fixed, together with another problem concerning \Z anchors in multiline strings.

When using the $1-$9 regular expression form, why does calling gsub(...) on one nil the others?

First, a working example:
string = "foo-bar-25-baz"
if string =~ /(.+)-(10|25)(?:-(baz))?/
puts $1
puts $2
puts $3
end
This produces 'foo-bar', '25' and 'baz' on three lines, as expected. But if we do this:
string = "foo-bar-25-baz"
if string =~ /(.+)-(10|25)(?:-(baz))?/
puts $1.gsub('-', ' ') # Here be the problem
puts $2 # nil
puts $3 # nil
end
the values of $2 and $3 are now nil. I have to puts $2 and puts $3 and then $1.gsub(...), and it will work. As far as I can tell this only applies to gsub and gsub!
This causes the same problem:
string = "foo-bar-25-baz"
if string =~ /(.+)-(10|25)(?:-(baz))?/
puts $3.gsub('hard', 'h')
puts $1 # nil
puts $2 # nil
end
I spent about 15 minutes debugging this and I'm wondering why.
gsub is most likely re-assigning those variables (as would pretty much any other function that uses the regexp engine). If you need to call gsub before using all your original match results, store them to a local variable first with something like match_results = [$1, $2, $3].

Resources