使用 PHP 将字符串拆分为数字和字符数组的正则表达式

Regex to split string into array of numbers and characters using PHP

我有一个类似于以下模式的算术字符串。

a. 1+2+3
b. 2/1*100
c. 1+2+3/3*100
d. (1*2)/(3*4)*100

需要注意的是
1.字符串永远不会包含空格。
2. 字符串将始终是数字、算术符号(+、-、*、/)和字符“(”和“)”的组合

我正在寻找 PHP 中的正则表达式,以根据字符的类型拆分字符并形成如下所示的单个字符串字符数组。
(注意:我不能使用str_split,因为我希望大于10的数字不被拆分。)

一个。 1+2+3
输出=> [
0 => '1'
1 => '+'
2 => '2'
3 => '+'
4 => '3'
]

b。 2/1*100
输出=> [
0 => '2'
1 => '/'
2 => '1'
3 => '*'
4 => '100'
]`

c。 1+2+3/3*100

输出=>[
0 => '1'
1 => '+'
2 => '2'
3 => '+'
4 => '3'
5 => '/'
6 => '3'
7 => '*'
8 => '100'
]`

d。 (1*2)/(3*4)*100

输出=>[
0 => '('
1 => '1'
2 => '*'
3 => '2'
4 => ')'
5 => '/'
6 => '('
7 => '3'
8 => '*'
9 => '4'
10 => ')'
11 => '*'
12 => '100'
]

非常感谢您。

使用这个正则表达式:
(?<=[()\/*+-])(?=[0-9()])|(?<=[0-9()])(?=[()\/*+-])

它将匹配数字或括号与运算符或括号之间的每个位置。
(?<=[()\/*+-])(?=[0-9()])匹配左边有括号或操作符,右边有数字或括号的位置
(?<=[0-9()])(?=[()\/*+-])同上,左右颠倒

演示 here

正如我所说,如果你能提供一些你自己完成的工作来解决这个问题,我会帮助你。

但是,如果在用算术表达式制作一维数组时,您的 objective 是解析和计算该数组,那么您应该构建一棵树,并通过将运算符作为节点来对其进行分层,分支是操作数:

'(1*2)/(3*4)*100'

Array
(
    [operand] => '*',
    [left] => Array
        (
            [operand] => '/',
            [left] => Array
                (
                    [operand] => '*',
                    [left] => 1,
                    [right] => 2
                ),
            [right] => Array
                (
                    [operand] => '*',
                    [left] => 3,
                    [right] => 4
                )
        ),
    [right] => 100
)

由于您声明表达式是 "clean",没有空格等,您可以拆分

\b|(?<=\W)(?=\W)

它在非单词字符之间的所有单词边界 边界上拆分(使用匹配两个非单词字符之间的位置的正环视)。

See an illustration here at regex101

不需要为此使用正则表达式。您只需遍历字符串并根据需要构建数组。

编辑,刚刚意识到使用 while 循环而不是两个 for 循环和 if() 可以更快地完成。

$str ="(10*2)/(3*40)*100";
$str = str_split($str); // make str an array

$arr = array();
$j=0; // counter for new array
for($i=0;$i<count($str);$i++){ 
    if(is_numeric($str[$i])){ // if the item is a number
        $arr[$j] = $str[$i]; // add it to new array 
        $k = $i+1;
        while(is_numeric($str[$k])){ // while it's still a number append to new array item.
            $arr[$j] .= $str[$k]; 
            $k++; // add one to counter.
            if($k == count($str)) break; // if counter is out of bounds, break loop.
        }
        $j++; // we are done with this item, add one to counter.
        $i=$k-1; // set new value to $i
    }else{
        // not number, add it to the new array and add one to array counter.
        $arr[$j] = $str[$i]; 
        $j++;
    }
}

var_dump($arr);

https://3v4l.org/p9jZp

您也可以使用这个匹配的正则表达式:[()+\-*\/]|\d+

Demo

我正在为 php 计算器演示做类似的事情。 A related post.

考虑 preg_split() 的这种模式:

~-?\d+|[()*/+-]~ (Pattern Demo)

这有一个额外的好处,即允许负数而不会使运算符混淆它们。第一个“替代”匹配正整数或负整数,而第二个“替代”(在 | 之后)匹配括号和运算符——一次一个。

在 php 实现中,我将整个模式放在捕获组中并保留分隔符。这样就不会留下任何子字符串。 ~ 用作模式分隔符,因此模式中的斜线不需要转义。

代码:(Demo)

$expression = '(1*2)/(3*4)*100+-10';
var_export(
    preg_split(
        '~(-?\d+|[()*/+-])~',
        $expression,
        0,
        PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
    )
);

输出:

array (
  0 => '(',
  1 => '1',
  2 => '*',
  3 => '2',
  4 => ')',
  5 => '/',
  6 => '(',
  7 => '3',
  8 => '*',
  9 => '4',
  10 => ')',
  11 => '*',
  12 => '100',
  13 => '+',
  14 => '-10',
)