问题
I've been Googling this regex behavior all afternoon.
$str = ' b c d w i e f g h this string';
echo preg_replace('/\s[bcdefghjklmnopqrstuvwxyzBCDEFGHJKLMNOPQRSTUVWXYZ]{1}\s/', ' ', $str);
I want to remove all instances of a single character by itself (except for A and I) and leave one space in its place. This code appears to work on every other match. I suspect this is because the matches overlap each other.
I suspect a lookaround would be appropriate here, but I've never used them before and could use a snippet.
EDIT: Just to avoid confusion about what I am trying to accomplish. I want to turn the above string into this:
$str = ' i this string';
Notice all single-letter characters that are NOT "A" or "I" have been removed.
回答1:
You can try this:
/(?<=\s)[b-hj-zB-HJ-Z](?=\s)/
or modify the ranges if you dont need both i and I.
回答2:
You can use look-arounds instead. They are 0-length matches, and hence would not consume spaces. And {1} is really absurd there, you can remove it.
echo preg_replace('/(?<=\s)[bcdefghjklmnopqrstuvwxyzBCDEFGHJKLMNOPQRSTUVWXYZ](?=\s)/', '', $str)
You can make use of range and case-insensitive flag (?i) here, to reduce the pain of typing all those characters:
echo preg_replace('/(?i)(?<=\s)[B-HJ-Z](?=\s)/', '', $str)
or word boundaries will also work here:
echo preg_replace('/(?i)\b[B-HJ-Z]\b/', '', $str)
回答3:
You can use this:
echo preg_replace('~(?i)\b[B-HJ-Z]\b~', ' ', $str);
Notice: instead of using spaces to delimit the single letter, I use word boundaries which are the zero width limit between a character from [a-zA-Z0-9_] and another character. This is more general than a space and include (for example) punctuation symbols.
来源:https://stackoverflow.com/questions/17958236/php-preg-replace-skipping-where-match-overlaps