将字符串拆分为数字和文本,但接受其中包含单个数字的文本

split string in numbers and text but accept text with a single digit inside

假设我想将这个字符串分成两个变量:

$string = "levis 501";

我会用

preg_match('/\d+/', $string, $num);
preg_match('/\D+/', $string, $text);

但是假设我想把这个一分为二

$string = "levis 5° 501";

作为$text = "levis 5°";$num = "501";

所以我的猜测是我应该在 preg_match('/\d+/', $string, $num); 中添加一个规则,该规则仅在字符串的末尾查找数字,并且我希望它介于 2 到 3 位数字之间。 而且 $text 匹配现在在里面有一个数字...

你会怎么做?

要将字符串分成两部分,请使用以下任一方法:

preg_match('~^(.*?)\s*(\d+)\D*$~s', $s, $matches);

这个正则表达式匹配:

  • ^ - 字符串的开头
  • (.*?) - 第 1 组捕获任何一个或多个字符,尽可能少(因为 *? 是一个 "lazy" 量词)最多...
  • \s* - 零个或多个空白符号
  • (\d+) - 第 2 组捕获 1 个或多个数字
  • \D* - 除数字以外的零个或多个字符(它是相反的 shorthand 字符 class 到 \d
  • $ - 字符串结尾。

~s 修饰符是一个 DOTALL 修饰符,它强制 . 匹配任何字符,即使是换行符,如果没有这个修饰符它就不匹配。

preg_split('~\s*(?=\s*\d+\D*$)~', $s);

这个\s*(?=\s*\d+\D*$)模式:

  • \s* - 零个或多个空格,但前提是后跟...
  • (?=\s*\d+\D*$) - 零个或多个空格后跟 1+ 个数字后跟 0+ 个字符,而不是数字后跟字符串结尾。

(?=...) 构造是一个积极的前瞻,它不消耗字符,只检查内部模式是否匹配,如果匹配,returns "true",如果不匹配,则不匹配发生。

参见IDEONE demo:

$s = "levis 5° 501";
preg_match('~^(.*?)\s*(\d+)\D*$~s', $s, $matches);
print_r($matches[1] . ": ". $matches[2]. PHP_EOL);
print_r(preg_split('~\s*(?=\s*\d+\D*$)~', $s, 2));