Live data from Hacker News

The dangers of single line regular expressions

greg.molnar.io

31–40 of 133 posts

Re: The dangers of single line regular expressions

#37
Raku (perl6) was a chance for Larry Wall to fix some of the limitations of the perl regex syntax, as you would expect from the perl heritage, it behaves similarly.

    ~ > raku -e 'say "foobar"   ~~ /^  +$/ ?? "yes" !! "no"'    
    yes
    ~ > raku -e 'say "foo\nbar" ~~ /^  +$/ ?? "yes" !! "no"'  
    no
    ~ > raku -e 'say "foo\nbar" ~~ /^^+$$/ ?? "yes" !! "no"'
    yes
- ^^ and $$ are the raku flavour of multiline mode

- ~~ the smartmatch operator binds the regex to the matchee and much more

- character classes are now (plain [...] does what (...) does in math)

- perl's triadic x ? y : z becomes x ?? y !! z

We can have whitespace in our regexen now (and comments and multiline regexen)

    my $regex =  rx/ \d ** 4            #`(match the year YYYY) 
                 '-'
                 \d ** 2                # ...the month MM 
                 '-'
                 \d ** 2 /;             # ...and the day DD 
 
    say '2015-12-25'.match($regex);     # OUTPUT: «「2015-12-25」␤»

Re: The dangers of single line regular expressions

#38
post #6

In my experience `$` does reliably mean end of string for regular expressions, unless you specifically ask for "multiline" mode. Ruby seems to be in multiline mode all the time? $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foobar") else "no"' yes $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\nbar") else "no"' no $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\…

Yeah, my takeaway from this was more "the dangers of Ruby" rather than "the dangers of single line regular expressions" (: I think the simplest fix would be to use "\Z" rather than "$", which means "match end of input" rather than "end of line." This is also Perl-compatible. So weird that the "$" default meaning is different in Ruby. I guess one could argue that Ruby's way is better since "$" has a fixed meaning, rat…

In case of ruby, best would be to actually use result of match for futher computation like this:

if !m=/^[a-z0-9 ]+$/match(str) return "Bad Input" end str=m[0]

Re: The dangers of single line regular expressions

#39
post #6

In my experience `$` does reliably mean end of string for regular expressions, unless you specifically ask for "multiline" mode. Ruby seems to be in multiline mode all the time? $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foobar") else "no"' yes $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\nbar") else "no"' no $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\…

The potential trouble with $ (even in single-line mode) is that it matches the end of a string BOTH with AND without a newline at the end. If you're using it to ensure the string has no newline before doing something with it, this can lead to trouble.

  $ python3 -c 'import re; print("yes" if re.search(r"^foo$", "foo") else "no")'
    yes

  $ python3 -c 'import re; print("yes" if re.search(r"^foo$", "foo\n") else "no")'
    yes

  $ python3 -c 'import re; print("yes" if re.search(r"\Afoo\Z", "foo") else "no")'
    yes

  $ python3 -c 'import re; print("yes" if re.search(r"\Afoo\Z", "foo\n") else "no")'
    no
Even if the newline is not problematic, using \A and \Z makes your intentions clearer to the reader, especially if you add re.X and place comments into the pattern.

Asides:

1. Based on syntax, you appear to be testing with python2.

2. With python, re.match is implicitly anchored to the start, so the ^ is redundant. Use re.search or omit the ^.

Post reply on HN