正则表达式匹配模式,除非它与特定字符串结束

I'm having a little trouble coming up with a regex for my particular situation. This is what I have.

"#<call:(\d+)>(?:(?!\/MM).)+?(\s+)?(?=\<)#ims"

I need to match the following example.

<call:5>anything <

But I don't want to match this...

<call:5>anything/mm <

That's working ok, but the problem is that it won't match this...

<call:5>anything/mmm <

I need the regex to match anything provided anything does not end with /mm. I know it's going to be something small I'm overlooking, but could you point out what I'm doing wrong please?

If one can assume that the call tag contents to be matched will not contain

  • spaces after an (allowed?) /mm string or
  • < characters (except at the end),

the following seems to work:

<call:(\d+)>(?:(?!\/mm[\s<]).)+?(\s+)?(?=\<)

EDIT:

I think the corner cases can be solved as well, try this instead:

<call:(\d+)>(?:(?!\/mm\s*?<).)+?(\s+)?(?=\<)

Is what you're trying to say is if the match ends with /mm < then it is invalid?

if (preg_match('%<call:(\d+)>(?!.*/mm <\z)(.*)%sim', $subject)) {
    # Successful match
} else {
    # Match attempt failed
}

if all line end in either /m or /mmm and you want "anything" you can add this '%<call:(\d+)>(?!.*/mm <\z)(.*)(?:/m+ <)%sim'