in reply to Pattern matching fields with variable or NULL data

Here's a couple of guesses at what you want:

/\d{0,3}/
matches:
"123"
"  123"
"123  "
"  123  "
"foo123bar"
doesn't match:
"1 2 3"

/^\s*\d{0,3}\s*$/
matches:
"123"
"  123"
"123  "
"  123  "
doesn't match:
"foo123bar"
"1 2 3"

/^\s*(?:\d\s*){0,3}$/
matches:
"123"
"  123"
"123  "
"  123  "
" 1 2 3 "
doesn't match:
"foo123bar"

Replies are listed 'Best First'.
Re^2: Pattern matching fields with variable or NULL data
by Anonymous Monk on Oct 27, 2004 at 00:57 UTC
    Thanks ikegami. /\d{0,3}/ works ok if there are three digits somewhere in the field.

    It doesn't match:
    "1 "
    "12 "
    " 1"
    " "

    To attempt to grab any digits in the field, or only white space, I have tried /\d{0,3}|\W{3}/.

    Haven't found any examples on the Web or the Perl reference that might assist as yet. Any suggestions?
      Hi ikegami,

      Figured it out.

      /\d{3}|\d\s\s|\d\d\s|\W{3}/

      Thanks for your help.

        That seems a bit over complicated.

        print $_, m[\s*(\d{0,3}\b)?] ? " contained '$1'" : ' contained nothing that matched' for '','1','1 ',' 1','12',' 12 ','123',' 123',' 123 ','1234','1 2 +3'; Use of uninitialized value in concatenation (.) or string at (eval 21) + line 1, <STDIN> line 19. contained '' 1 contained '1' 1 contained '1' 1 contained '1' 12 contained '12' 12 contained '12' 123 contained '123' 123 contained '123' 123 contained '123' 1234 contained '' 1 2 3 contained '1'

        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

        That doesn't match "12 ", which you said should be matched.

        Also, \s should be used instead of \W (unless you want to match things like "!@#").

      hum, it does matches all of those

      print( "1 " =~ /\d{0,3}/ ?"match":"no match", $/); print( "12 " =~ /\d{0,3}/ ?"match":"no match", $/); print( " 1" =~ /\d{0,3}/ ?"match":"no match", $/); print( " " =~ /\d{0,3}/ ?"match":"no match", $/);

      Now, if you want the regexp to completely match exactly three characters, consiting of 0+ digits padded with spaces on either side, that's much more complicated.

      We can write it out the long way:
      /^(?:   |  \d| \d\d|\d\d\d|\d  |\d\d |\d  )$/
      This doesn't compress well.

      /^[ \d]{3}$/
      will match them all, but it will also match "1 2".

      /^(?: [ \d]{2}|[ \d]{2} |\d{3})$/ will work.

      Anything else I can think of invovles potentially matching more than three characters (/^\s*\d{0,3}\s*$/) or involves more than a regexp.

      If the spaces can only be leading spaces, then the long form would be:
      /^(?:   |  \d| \d\d|\d\d\d)$/
      which doesn't really simplify.

      btw, you should be using \D if you mean non-digit, or \S if you mean non-whitespace. \W doesn't appear to be appropriate here.