如何用PHP将单个字符串中的字符串分隔?

时间:2018-01-08 21:47:44

标签: php regex preg-split

我有AK747这个词,我使用正则表达式来检测一个字符串(至少2个字符ex:AK)后面跟一个数字(至少是数字ex:747)。 编辑:(对不起,我不清楚这些家伙) 我需要在上面执行此操作,因为:

在某些情况下,我需要拆分以匹配AK-747的搜索。当我搜索字符串' AK-747'关键字' AK747'除非我在数据库中使用levenshtein,否则它不会找到匹配,所以我更喜欢将AK747拆分为AK和747。

我的代码:

$strNumMatch = preg_match('/^[a-zA-Z]{2,}[0-9]{2,}$/', 
$value, $match);

if(isset($match[0]))
    echo $match[0];

如何使用preg_split()或任何其他方式拆分为数组[' AK',' 747']?

4 个答案:

答案 0 :(得分:1)

你可以试试这个:

preg_match('/[0-9]{2,}/', $value, $matches, PREG_OFFSET_CAPTURE);
$position = $matches[0][1];
$letters = substr($value, 0, $position);
$numbers = substr($value, $position);

这样你就可以获得第一个数字的位置并在那里分开。

修改: 从你原来的方法开始,这可能看起来像这样:

$strNumMatch = preg_match('/^([a-zA-Z]{2,})([0-9]{2,})$/', $value, $match, PREG_OFFSET_CAPTURE);
if($strNumMatch){
    $position = $matches[2][1];
    $letters = substr($value, 0, $position);
    $numbers = substr($value, $position);
    $alternative = $letters.'-'.$numbers;
}

答案 1 :(得分:1)

$input = 'AK-747';

if (preg_match('/^([a-z]{2,})-?([0-9]{2,})$/i', $input, $result)) {
    unset($result[0]);
}

print_r($result);

输出:

Array
(
    [1] => AK
    [2] => 747
)

答案 2 :(得分:1)

preg_split()是一个非常明智和直接的调用,因为你需要一个包含两个子串的索引数组。

代码:(Demo

$input = 'AK-747';
var_export(preg_split('/[a-z]{2,}\K-?/i',$input));

输出:

array (
  0 => 'AK',
  1 => '747',
)

\K表示"重启全字符串匹配"。实际上,\K左边的所有内容都保留为结果数组中的第一个元素,而右边的所有内容(可选连字符)都被省略,因为它被认为是分隔符。 Pattern Demo

代码:(Demo

我处理了一小部分输入信息,以显示可以执行的操作并在摘录后解释。

$inputs=['AK747','AK-747','AK-','AK'];  // variations as I understand them
foreach($inputs as $input){
    echo "$input returns: ";
    var_export(preg_split('/[a-z]{2,}\K-?/i',$input,2,PREG_SPLIT_NO_EMPTY));
    echo "\n";
}

输出:

AK747 returns: array (
  0 => 'AK',
  1 => '747',
)
AK-747 returns: array (
  0 => 'AK',
  1 => '747',
)
AK- returns: array (
  0 => 'AK',
)
AK returns: array (
  0 => 'AK',
)

preg_split()采用一种模式,该模式接收与变量子字符串匹配的模式,并将其用作分隔符。如果每个输入字符串中都存在-,则explode('-',$input)最合适。但是,-在此任务中是可选的,因此模式必须允许-是可选的(这是?量词在此页面上的所有模式中的作用)。

现在,您无法使用/-?/that would split the string on every character这样的模式。要解决此问题,您需要告诉正则表达式引擎可选-的确切预期位置。您可以通过在[a-z]{2,}(单个预定分隔符)之前引用-?来执行此操作。

模式/[a-z]{2,}-?/i可以很好地找到可选连字符的正确位置,但现在问题是,字符串中的前导字母包含在part of the delimiting substring中。

有时,#34; lookarounds&#34;可以在正则表达式模式中使用以匹配但不消耗子字符串。 A&#34;积极的背后&#34;用于匹配前面的子字符串,但"variable length lookbehinds" are not permitted in php (and most other regex flavors)。这就是无效模式的样子:/(?<=[a-z]{2,})-?/i

围绕这种技术性的方法是重新开始全字符串匹配&#34;在可选连字符之前使用\K标记(又名a lookbehind alternative)。要正确地仅针对预期的分隔符,必须使用前导字母匹配/消费&#34;然后&#34;丢弃&#34; - 这是\K的作用。

至于包含preg_split() ...

的第3和第4个参数
  • 我已将第3个参数设为2。这与limit具有的explode()参数类似。它指示函数不要生成超过2个输出元素。对于这种情况,我可以使用NULL-1表示&#34;无限制&#34;,但我不能将参数留空 - 必须将其指定为允许声明第四个参数。
  • 我已将第4个参数设置为PREG_SPLIT_NO_EMPTY,指示函数不生成空输出元素。

钽沓!

P.S。 preg_match_all() solution与使用管道和两个锚点一样简单:

$inputs=['AK747','AK-747','AK-','AK'];  // variations as I understand them
foreach($inputs as $input){
    echo "$input returns: ";
    var_export(preg_match_all('/^[a-z]{2,}|\d{2,}$/i',$input,$out)?$out[0]:[]);
    echo "\n";
}
// same outputs as above

答案 3 :(得分:0)

您可以使-选择?

/([A-Za-z]{2,}-?[0-9]{2,})/

https://regex101.com/r/tIgM4F/1