在字母序列和数字序列之间只拆分字符串一次


Split string only once between sequence of letters and sequence of numbers

我想从一个可预测的格式化字符串中提取两个子字符串。

每个字符串由字母和数字组成。

输入,输出:

  • MAU120 =>MAU120
  • MAUL345 =>MAUL345
  • MAUW23 =>MAUW23
$matches = array();
if ( preg_match('/^([A-Z]+)([0-9]+)$/i', 'MAUL345', $matches) ) {
    echo $matches[1]; // MAUL
    echo $matches[2]; // 345 
}

如果你需要MAU,你可以这样做:

/^(MAU[A-Z]*)([0-9]+)$/i

删除末尾的i修饰符将使regex区分大小写。

试试这个正则表达式:

/('D*)('d*)/
PHP代码:

$matches = array();
var_dump( preg_match('/('D*)('d*)/', 'MAUL345', $matches) );
var_dump( $matches );

从你的例子中逐字引用:

<?php
$tests = array('MAU120', 'MAUL345', 'MAUW23', 'bob2', '?@#!123', 'In the MAUX123 middle.');
header('Content-type: text/plain');
foreach($tests as $test)
{
    preg_match('/(MAU[A-Z]?)('d+)/', $test, $matches);
    $str = isset($matches[1]) ? $matches[1] : '';
    $num = isset($matches[2]) ? $matches[2] : '';
    printf("'$str = %s'n'$num = %d'n'n", $str, $num);
}
?>

生产:

$test = MAU120
$str = MAU
$num = 120
$test = MAUL345
$str = MAUL
$num = 345
$test = MAUW23
$str = MAUW
$num = 23
$test = bob2
$str = 
$num = 0
$test = ?@#!123
$str = 
$num = 0
$test = In the MAUX123 middle.
$str = MAUX
$num = 123

当您可以保证将有一个或多个非数字,然后有一个或多个数字时,您可以调用sscanf()来解析字符串

本机函数与preg_match()相比有许多优点。

  1. 它不返回完整字符串匹配。
  2. 它允许你根据你使用的格式占位符类型强制转换子字符串。
  3. 它可以返回它的数组或创建引用变量——取决于你提供给它的参数的数量。

代码(演示):

$tests = [
    'MAU120',
    'MAUL345',
    'MAUW23',
];
foreach ($tests as $test) {
    sscanf($test, '%[^0-9]%d', $letters, $numbers);
    var_export([$letters, $numbers]);
    echo "'n";
}

输出:(注意数字被强制转换为整数类型)

array (
  0 => 'MAU',
  1 => 120,
)
array (
  0 => 'MAUL',
  1 => 345,
)
array (
  0 => 'MAUW',
  1 => 23,
)

如果您的数字可能以零开始,并且您希望保留它们,您可以使用%s而不是%d来捕获非空白子字符串。如果您使用%s,那么数字将被强制转换为字符串而不是int型。

可选语法:(Demo)

foreach ($tests as $test) {
    var_export(sscanf($test, '%[^0-9]%d'));
    echo "'n";
}