问题
I'm trying to write a very simple regular expression that matches any file name that doesn't end in .php. I came up with the following...
(.*?)(?!\.php)$
...however this matches all filenames. If someone could point me in the right direction I'd be very grateful.
回答1:
Almost:
.*(?!\.php)....$
The last four dots make sure that there is something to look ahead at, when the look-ahead is checked.
The outer parentheses are unnecessary since you are interested in the entire match.
The reluctant .*?
is unnecessary, since backtracking four steps is more efficient than checking the following condition with every step.
回答2:
Instead of using negative lookahead, sometimes it's easier to use the negation outside the regex at the hosting language level. In many languages, the boolean
complement operator is the unary !
.
So you can write something like this:
! str.hasMatch(/\.php$/)
Depending on language, you can also skip regex altogether and use something like (e.g. Java):
! str.endsWith(".php")
As for the problem with the original pattern itself:
(.*?)(?!\.php)$ // original pattern, doesn't work!
This matches, say, file.php
, because the (.*?)
can capture file.php
, and looking ahead, you can't match \.php
, but you can match a $
, so altogether it's a match! You may want to use look behind, or if it's not supported, you can lookahead at the start of the string.
^(?!.*\.php$).*$ // negative lookahead, works
This will match all strings that does not end with ".php"
using negative lookahead.
References
- regular-expressions.info/Lookarounds
Related questions
- How does the regular expression (?<=#)[^#]+(?=#) work?
回答3:
You are at the end of the string and looking ahead. What you want is a look behind instead:
(.*)$(?<!\.php)
Note that not all regular expression engines support lookbehind assertions.
来源:https://stackoverflow.com/questions/3404037/how-to-make-a-regex-for-files-ending-in-php