I want to capture a pattern upto but not including the first instance of an optional other pattern with preg_match, eg:
ABCDEFGwTW$% | capture ABCD
@Q%HG@H%hg afdgwsa g weg#D DEFG | capture @Q%HG@H%hg afdgwsa g weg#D D
@Q%HDEFG@H%hg afdgwsa g weg#D DEFG | capture @Q%HD
So in the above case anything before the first instance of the string EFG
is captured. also, if the EFG
string is not present then I want to capture the whole string.
I would have thought that the following would work, but no such luck:
$pattern = '/(.*)(?:EFG)?/';
preg_match($pattern, 'Q$TQ@#%GEFG开发者_Python百科w35hqb', $matches);
print_r($matches);
//should give: 'Q$TQ@#%G'
You can use
'/(.*?)(?=EFG|$)/'
Try this: (.*?)(?:EFG|$)
This will match any character (as few as possible) until it finds EFG.
Another way to do it:
$str = 'Q$TQ@#%GEFGw35hqb';
$res = preg_split('/EFG/', $str);
print_r($res);
You can have the result with a lot less confusion:
Just check a simpler version of the pattern to match, and if not, use the original string:
<?php
$match = 'Q$TQ@#%GEFGw35hqb';
if (preg_match('/^(.*)EFG/', $match, $matches)) {
$match = $matches[1];
}
echo $match;
Using preg_match()
with a pattern that uses lazy matching and a lookahead is going to take more steps than just using preg_replace()
with greedy matching (and no lookarounds) and simply replacing the optional match with an empty string. If the needle doesn't exist, then nothing is changed in the string. Super easy.
Code: (Demo)
$strings = [
'ABCDEFGwTW$%',
'@Q%HG@H%hg afdgwsa g weg#D DEFG',
'@Q%HDEFG@H%hg afdgwsa g weg#D DEFG',
'No needle in the haystack',
];
var_export(preg_replace('/EFG.*/', '', $strings));
Output:
array (
0 => 'ABCD',
1 => '@Q%HG@H%hg afdgwsa g weg#D D',
2 => '@Q%HD',
3 => 'No needle in the haystack',
)
精彩评论