Php 正则表达式捕获第一个可选字符串之前的所有内容

Php 正则表达式捕获第一个可选字符串之前的所有内容,php,regex,Php,Regex,我想捕获一个模式,但不包括带有preg_match的可选其他模式的第一个实例,例如: 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 因此,在上述情况下,捕获字符串EFG的第一个实

我想捕获一个模式,但不包括带有preg_match的可选其他模式的第一个实例,例如:

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
因此,在上述情况下,捕获字符串
EFG
的第一个实例之前的任何内容。另外,如果
EFG
字符串不存在,那么我希望捕获整个字符串

我本以为以下方法会奏效,但没有这样的运气:

$pattern = '/(.*)(?:EFG)?/';
preg_match($pattern, 'Q$TQ@#%GEFGw35hqb', $matches);
print_r($matches);
//should give: 'Q$TQ@#%G'
试试这个:
(.*)(:EFG |$)

这将匹配任何字符(尽可能少),直到找到EFG。

您可以使用

'/(.*?)(?=EFG|$)/'

您可以在不太混乱的情况下获得结果:

只需检查要匹配的模式的更简单版本,如果不匹配,则使用原始字符串:

<?php
$match = 'Q$TQ@#%GEFGw35hqb';
if (preg_match('/^(.*)EFG/', $match, $matches)) {
    $match = $matches[1];
}

echo $match;
另一种方法:

$str = 'Q$TQ@#%GEFGw35hqb';
$res = preg_split('/EFG/', $str);
print_r($res);
preg_match()
与使用惰性匹配和前瞻性的模式一起使用,要比仅将
preg_replace()
与贪婪匹配(且不使用前瞻性)一起使用以及仅用空字符串替换可选匹配采取更多步骤。如果针不存在,则字符串中没有任何更改。超级容易

代码:()

输出:

array (
  0 => 'ABCD',
  1 => '@Q%HG@H%hg afdgwsa g   weg#D D',
  2 => '@Q%HD',
  3 => 'No needle in the haystack',
)

问题是它不会匹配不包含EFGRight的字符串,哦!也要匹配行尾字符。(更新的答案。)抱歉@Josh M,@Jens击败了你:P没关系,我的错是没有满足要求。注意,即使是更新的版本也不正确:它实际上在结果中包含可选字符串(而问题是“在第一个可选字符串之前捕获所有内容”)啊,非常好-我没有想到匹配EFG或结尾:)是的,我也可以用
stripos
做类似的事情,但我想我应该了解一下regex-它更整洁(是的;)但是,如果性能是一个问题,您应该使用
strpos
;)或者更好的是
list($match)=preg_split('/EFG/',$haystack)
直接将字符串捕获到VARABLE:)使用带有文字模式的
preg_
调用是不必要的开销。为什么不直接用EFG分解()
array (
  0 => 'ABCD',
  1 => '@Q%HG@H%hg afdgwsa g   weg#D D',
  2 => '@Q%HD',
  3 => 'No needle in the haystack',
)