From: Brian Candler Date: 2003-04-27T20:41:04+09:00 Subject: Regexp and $ I seem to remember some discussion about regexps recently, including Perl regexps versus Ruby regexps. I am actually in favour of Ruby regexps pretty much as they are, but I have one gripe: it doesn't seem to be possible to make "$" match "end of string" rather than "before a newline". I wrote a regexp which I thought would match trailing \n's in a string: a.gsub!(/\n+$/,'') This is pretty standard stuff in Perl: perl -e '$a="abc\ndef\n"; $a =~ s/\n+$//; print "<$a>\n";' But it doesn't work in Ruby. Adding /m doesn't help either. It took a fair bit of head-scratching and digging around for me to discover that to match the end of a string you must use '\z'. In Perl, I believe "^" and "$" match the start and end of the string only, unless you have multiline mode enabled. A bit of playing around shows: ^ matches $ matches . matches --------- --------- --------- Ruby // start of string end of string any char except \n or after \n or before \n [*note*] Ruby //m start of string end of string any char or after \n or before \n Perl // start of string end of string any char except \n Perl //m start of string end of string any char except \n or after \n or before \n Perl //s start of string end of string any char Perl //ms start or string end of string any char or after \n or before \n So it looks like Ruby's "normal" mode is like Perl's "multiline" mode, and there is no way to get Perl's "normal" mode in Ruby. Ruby's "multiline" mode is really Perl's "/ms" mode [*note*] Actually, that's not even true. Perl's $ will match end-of-string *after* a newline even in multiline mode: $ perl -e '$a="abc\n"; $a =~ s/c\n$//m; print "<$a>\n";' But Ruby can't. $ ruby -e 'a="abc\n"; a.gsub!(/c\n$/,""); puts "<#{a}>";' This means the description "$ matches end of string or before \n" is wrong for Ruby. In fact, I'm not sure *what* exactly $ matches. Can anybody give me a description of what $ matches in Ruby? I think this difference in behaviour is unfortunate, as I consider that "^" and "$" are part of the lowest-common-denominator of regexp behaviour which ought to be reasonably portable. Regards, Brian.