在前导数字和尾随字母之间拆分包含字母数字的字符串

25

我有一个字符串:

$Order_num = "0982asdlkj";
我该如何将其拆分成2个变量,一个包含数字元素,另一个包含字母元素?
数字元素长度可以是1到4,字母元素填充其余部分,使得每个order_num总共有10个字符。
我已经找到了PHP的explode函数,但不知道如何在我的情况下使用它,因为数字的数量在1到4之间,而字母在其后是随机的,所以无法按特定字母拆分。
6个回答

36

您可以使用 preg_splitlookahead 和 lookbehind 进行操作:

print_r(preg_split('#(?<=\d)(?=[a-z])#i', "0982asdlkj"));

打印
Array
(
    [0] => 0982
    [1] => asdlkj
)

如果字母部分仅包含字母而没有数字,则此方法才有效。

更新:

为了澄清这里正在发生的事情:

正则表达式查看每个位置,如果该位置之前有数字((?<=\d)) 并且 该位置之后是字母((?=[a-z])),则匹配并在该位置拆分字符串。整个过程不区分大小写(i)。


2
使用split相比match有什么优势? - moinudin
1
你需要转义 \d 中的 \。 - moinudin
3
@Col. Shrapnel:问题并不总是只有一个真正的答案。人们的思维方式各不相同,了解不同的解决问题的方法更好! - Felix Kling
当然可以。但是这个新手会把你的代码当作魔法咒语来使用,没有丝毫理解。而直接使用 preg_match 会更易读,人们可以从中开始学习正则表达式。 - Your Common Sense
3
讨论已经结束了。我只是想展示一种方法。如果有些人想要唯一真正的解决方案,那就去生活在一个美丽新世界吧,这不是我的错。别忘了答案不仅仅是为提问者准备的,也是为后来的人做准备的… - Felix Kling
显示剩余15条评论

7

使用 preg_match() 函数和正则表达式 (\d+)([a-zA-Z]+)。如果你想将数字限制在 1-4 个,字母限制在 6-9 个,可以改为 (\d+{1,4})([a-zA-Z]{6,9})

preg_match("/(\\d+)([a-zA-Z]+)/", "0982asdlkj", $matches);
print("Integer component: " . $matches[1] . "\n");
print("Letter component: " . $matches[2] . "\n");

输出:

Integer component: 0982
Letter component: asdlkj

http://ideone.com/SKtKs


1
$matches = array(); 这行代码其实并不必要。即使没有匹配,preg_match 也会确保数组始终存在。 - codaddict
1
此外,在 \d+ 中你不需要转义 \。只有 \d+ 就足够了。 - codaddict
1
@codaddict:在我看来,这是一种良好的编码风格,对于不太熟练的PHP程序员来说更易于理解。 - Felix Kling
1
@codaddict 我不知道 array(),但我不喜欢不转义。 - moinudin
或者使用这个更简单的表达式:/(\d+)(.*)/ - marcovtwout

5
您也可以使用preg_split函数,在数字和字母之间的位置拆分输入内容:
list($num,$alpha) = preg_split('/(?<=\d)(?=[a-z]+)/i',$Order_num);

2
你可以使用正则表达式来实现这一点。
preg_match('/(\d{1,4})([a-z]+)/i', $str, $matches);
array_shift($matches);
list($num, $alpha) = $matches;

我不会对数量使用严格的限制,但除此之外,这是最明智的答案。 - Your Common Sense

0

我更喜欢使用sscanf()方法,因为它简洁明了,不需要正则表达式,可以将数字部分转换为整数类型,并且不会像preg_match()一样生成不必要的完整字符串匹配。但是,%s需要确保字符串中字母部分没有空格。

演示

$Order_num = "0982asdlkj";
var_export (
    sscanf($Order_num, '%d%s')
);

这也可以设置为声明单个变量。

sscanf($Order_num, '%d%s', $numbers, $letters)

如果想使用 preg_ 函数,preg_split() 是最合适的选择,但我不会使用昂贵的环视。匹配数字,然后忘记它们(使用 \K)。这将在不消耗任何字符的情况下拆分字符串。演示
var_export (
    preg_split('/\d+\K/', $Order_num)
);

使用“对称数组解构”来分配变量。
[$numbers, $letters] = preg_split('/\d+\K/', $Order_num);

除了这些单一功能的方法,还会有很多双重功能的方法,比如:

$numbers = rtrim($Order_num, 'a..z');
$letters = ltrim($Order_num, '0..9');

但我不会在专业脚本中使用它们,因为它们缺乏优雅。


0

看看这个

<?php
$Order_num = "0982asdlkj";
$split=split("[0-9]",$Order_num);
$alpha=$split[(sizeof($split))-1];
$number=explode($alpha, $Order_num);
echo "Alpha -".$alpha."<br>";
echo "Number-".$number[0];
?>

致敬

wazzy


将您的PHP从古老版本升级到现代版本并再次运行。 - Your Common Sense
@Wazzy:因为人们很疯狂,他们会对他们不喜欢的答案进行投票。公平地说,你的解决方案并不是非常优雅,但它给出了正确的解决方案。我不会点赞它,但我也不会投反对票。+1来补偿。 - Felix Kling
@Col. Shrapnel:在 PHP 5.3.3 上运行良好。 - Felix Kling
2
@Col. Shrapnel:在PHP 5.3中,split已经被弃用,可以使用preg_split代替...但是无论是split还是preg_split都可以正常工作。我反对没有解释就进行投票否决,而将您的PHP从古老版本升级到现代版本并再次运行不是一个解释。 - Felix Kling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接