简体   繁体   中英

php regex match a word but don't match these other ones

I'm trying to sort though a list of pipe fittings using PHP with regex, I know how to match more then one word but I can't figure out how to not match words. I need it to not match "bolts" and "nuts"(with or without the s).

Sort list simple

0 - 2"x6" black nipple

0 - 1/2x4 black nipple

20 - 3/4" x 3/8" black bushing.

10 - 3/4" black plugs thread

0 - 7/8 x 3 3/4 black bolts

0 -7/8 black nuts

if(preg_match('/black|union/', $_POST["fitting_name$x"])){  
echo "show results";
}

Seems like I need to be looking at negative lookahead I tried .(?!bolts) also without the dot but didn't work for me. I tried a few other things but got to a point where I was just throwing things at it hoping for something to stick.

I'm really bad at regex so I may have seen the right way to do it but couldn't figure out how to make it work. Also thanks for any help you can give.

You can use negative lookaheads:

/^(?!.*\b(bolt|nut)s?\b).*(black|union)/
/                                         : Starting delimiter
 ^                                        : Matches the start of the string
  (?!                                     : Start of negative lookahead
     .*                                   : Matches any character 0 or more times
       \b                                 : Matches a word boundary before the target word
         (bolt|nut)                       : Literal match "bolt" OR "nut"
                   s?                     : Matches an optional "s"
                     \b                   : Matches a word boundary after the target word
                       )                  : End of negative lookahead
                        .*                : Match any charachter 0 or more times
                          (black|union)   : Literal match "black" OR "union"
                                       /  : Ending delimiter

Using the \b either side of the word means that you don't accidentally filter out words which contain the word bolt|nut for example: bolted flange .

$stringList = [
    '0 - 2"x6" black nipple',
    '0 - 1/2x4 black nipple',
    '20 - 3/4" x 3/8" black bushing.',
    '10 - 3/4" black plugs thread',
    '0 - 7/8 x 3 3/4 black bolts',
    '0 -7/8 black nuts'
];

foreach($stringList as $string){
    var_dump(
        preg_match('/^(?!.*\b(bolt|nut)s?\b).*(black|union)/', $string)
    );
}

/* Output...

int(1)
int(1)
int(1)
int(1)
int(0)
int(0)

i.e. matches for all but the last 2!
*/

You can consider using a pattern like

/\b(?:black|unions?)\b(?!.*\b(?:bolt|nut)s?\b)/

Add i after last / to make it case insensitive if needed. See the regex demo .

Details :

  • \b - a word boundary
  • (?:black|unions?) - black , union or unions
  • \b - a word boundary
  • (?.?*\b(:?bolt|nut)s?\b) - a negative lookahead that fails the match if, immediately to the right of the current location, there is
    • .* - any zero or more chars other than line break chars as many as possible
    • \b(?:bolt|nut)s?\b - bolt / bolts , nut / nuts as whole words.

Such pattern should work: ^(?.?*bolts.\b|?*nuts.\b).*$ (I replaced blot with bolt !) It actually uses negative lookahead but takes into account that there could be more letters .* before the word bolt or nut , s? to take into account plural form that is used 0 or 1 times, \b to match end of the word, so that word nutss would still match.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM