spraff spraff - 2 months ago 10
Perl Question

Why do these impossible-looking regexes match these strings?

In Perl I have

if ($_ =~ /$search/)
{
print STDERR "$search matches $_";
...


which outputs

^[\s\t]*#?[\s\t]*unix_listener[\s\t\]+auth-userdb[\s\t]* matches unix_listener lmtp {
^[\s\t]*#?[\s\t]*unix_listener[\s\t\]+auth-userdb[\s\t]* matches unix_listener auth-userdb {
^[\s\t]*#?[\s\t]*unix_listener[\s\t\]+auth-userdb[\s\t]* matches #unix_listener /var/spool/postfix/private/auth {
^[\s\t]*#?[\s\t]*unix_listener[\s\t\]+auth-userdb[\s\t]* matches unix_listener dict {


This seems impossible since only one of the
$_
strings contains
auth-userdb


Even weirder, by adding a
\{
to the end of the regex I get

^[\s\t]*#?[\s\t]*unix_listener[\s\t\]+auth-userdb[\s\t]*\{ matches unix_listener lmtp {


but no other matches (on the same input).

I thought I understood regexes of this type completely, but I can't figure out the logic here.

Someone please explain


  • why the first four
    $_
    lines match
    $search
    instead of only the one which contains
    auth-userdb

  • why adding the
    \{
    to the regex eliminated all but one match.


Answer

Look at the char class you wrote:

Start                 End
|                       |
v                       v
[\s\t\]+auth-userdb[\s\t]
      ^
      |
      Because this is escaped

So you effectively have

[abdeh-u\[\]\+\s\t]

Replace whole regex with ^\s*#?\s*unix_listener\s+auth-userdb\s* since \t is included within \s.

Comments