问题
Performing a regular expression match in PHP using the preg suite, I understand that you can represent a conditional statement right within the regex.
I could hardly find any documentation online so I turned to Jeffrey E.F. Friedl's Mastering Regular Expressions.
The way I see it, something like /(?(?<=NUM:)\d+|\w+)/
should match a digit when it is preceded by NUM:
otherwise it should match a word.
But for some weird reason it always returns true and the match data doesn't make sense to me either. Can someone explain to me what's going on?
What I want to do is this:
preg_replace('/creat(?:e|ing)/i', 'make', $input)
but only when '/creat(?:e|ing)/i' is not surrounded by quotes.
in action, the input-output sequence I need is:
- input: create a white shirt.
output: make a white shirt.
- input: "create a white shirt."
output: "create a white shirt"
- input: hello create some good code.
output: hello make some good code.
- input: "hello" "make some" good "code."
output: "hello" "make some" good "code."
Thank you everybody!
Edit: I want to do something like: if there is an opening quote, make sure it has a closing pair before matching the keyword create
in this case. Hope that makes sense and is possible.
回答1:
You do not need any conditional constructs to skip what is inside quotes. There are two ways.
Use an alternative branch matching a quoted substring and use (*SKIP)(*FAIL)
verbs:
preg_replace('/"[^"]*"(*SKIP)(*F)|creat(?:e|ing)/i', 'make', $input)
Pattern details:
"[^"]*"
- matches"
, then 0+ characters other than"
and then a"
(*SKIP)(*F)
- make the regex engine discard the currently matched text and proceed from the current index|
- or...creat(?:e|ing)
- matchcreate
orcreating
.
See demo
Another way is mere using capturing and using preg_replace_callback
where you can check if a group was matched (and base the replacement logic appropriately):
preg_replace_callback('/("[^"]*")|creat(?:e|ing)/i', function($m) {
return !empty($m[1]) ? $m[1] : 'make';
}, $input)
See the IDEONE demo
Pattern details:
("[^"]*")
- Group 1 (can be later referenced with$1
from the replacement pattern) - a double quoted string|
- orcreat(?:e|ing)
- matchcreate
orcreating
.
Note that "[^"]*"
is a sample regex, if you need to match C strings with escaped sequences, you should use at least "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"
(in the code).
来源:https://stackoverflow.com/questions/37137668/conditional-regex-in-php-doesnt-seem-to-work