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

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

问题描述:

我有一个算术字符串,将类似于以下模式。正则表达式将字符串拆分为数组和字符使用PHP

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

需要注意的事项是
1.字符串绝不会包含空格。
2.字符串将始终是数字,算术符号(+, - ,*,/)和字符'('和')'的组合

我正在寻找一个PHP正则表达式来分割字符基于它们的类型并形成如下的单个字符串字符的数组。

一个(注意,因为我想数字比10不被分裂更大的我不能使用str_split)。 1+2+3
输出=>[
0 => '1'
1 => '+'
2 => '2'
3 => '+'
4 => '3'
]

2/1*100
输出=>[
0 => '2'
1 => '/'
2 => '1'
3 => '*'
4 => '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'
]

非常感谢你提前。

+2

欢迎来到StackOverflow。不幸的是,这既不是教程网站,也不是网络搜索替代品然而,我们可以帮助解决[某些主题上的问题](https://stackoverflow.com/help/on-topic),但它是**你的**工作[付出一些努力](http:// meta。 stackoverflow.com/questions/261592),其中包括初级[(重新)搜索](https://google.com/)。 –

+0

尽量做到这一点,并提供代码,我会与你分享一个更简单的方法来做到这一点。 – ksjohn

+1

你最好为这样的工作写一个解析器。 – Toto

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

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

演示here

+0

谢谢。正则表达式似乎工作,但是当我运行下面的代码 - $ re ='/(?数组:1 [▼ 0 => “” ] 1 =>数组:1 [▼ 0 => “” ] ]我想有数组作为( 1,+,2,+,3)。 –

+0

我运行错了吗。谢谢,但我很少使用正则表达式,因此无法开始工作。 –

+0

@ChaitraHegde我想你想使用preg_split函数,而不是preg_match_all。 http://php.net/manual/fr/function.preg-split.php – Gawil

正如我所说的,我会帮助你,如果你能提供一些工作,你没有通过自己来解决这个问题。但是,如果从算术表达式中构造出一维数组,则您的目标是解析并合并该数组,然后您应该构建一棵树,并通过将操作符作为节点进行层次化,分支是操作数:

'(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 
) 

既然你声明的表述是“干净”的,没有空格或这样,你可能分裂的

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

它分割上的所有单词边界 BOU ndaries之间的非单词字符(使用肯定的lookarounds匹配两个非单词字符之间的位置)。

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,NULL,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', 
) 
+0

@ChaitraHegde当使用四个测试用例字符串比较当前接受的答案和我的模式之间的步骤效率时,我的方法将大致快4倍。这个答案可以与我的其他帖子合并,以允许小数点,如果你愿意。 – mickmackusa