将字符串按正则表达式分割成数组(PHP)

5

我需要将下面的字符串拆分成类似以下格式的数组键:

字符串 = "(731) 文本内容2 (220) 其他文本54数字内容" 转换为:

array( 
  '731' => 'some text here with number 2', 
  '220' => 'some 54 number other text here' 
);

我尝试过:
preg_split( '/\([0-9]{3}\)/', $string ); 

并获得:
array ( 
  0 => 'some text here', 
  1 => 'some other text here' 
); 

我认为,你应该以更好的格式呈现所涉及的数据。这样社区就更容易阅读和回复了。 - Bhavik Shah
1
需求太模糊了。你能否至少提供所提供输入字符串的预期输出? - Wiktor Stribiżew
你自己尝试过什么了吗? - syck
你试过什么吗? - Avishake
我猜您希望字符串中的数字成为数组中的键,是吗? - Henders
显示剩余2条评论
6个回答

8

代码

$string = "(731) some text here with number 2 (220) some 54 number other text here";

preg_match_all("/\((\d{3})\) *([^( ]*(?> +[^( ]+)*)/", $string, $matches);
$result = array_combine($matches[1], $matches[2]);

var_dump($result);

输出

array(2) {
  [731]=>
  string(28) "some text here with number 2"
  [220]=>
  string(30) "some 54 number other text here"
}

ideone 演示


描述

正则表达式使用:

  • \((\d{3})\) 匹配括号中的 3 个数字并捕获它(组 1)
  • \ * 匹配键和值之间的空格
  • ([^( ]*(?> +[^( ]+)*) 匹配除 ( 外的所有内容并捕获它(组 2)
    此子模式与 [^(]*(?<! ) 完全匹配,但基于展开循环技术更加高效。

    *请注意,我解释了值字段中不能有 ( 的情况。如果不是这种情况,请告诉我,我会相应地进行修改。

之后,我们就可以用 $matches[1] 表示 keys,用 $matches[2] 表示 values。通过使用 array_combine() 函数生成所需的数组。


仅因使用了array_combine()而获得点赞。您的正则表达式存在两个问题:1- 不必要的占有量词。2- 忽略字符串中可能存在的括号。 - revo
为什么您认为\s*+[^( ]*+可能存在失败情况? - revo
哈哈!没错!我真不知道我在想什么。谢谢你提醒我。 - Mariano

1

试试这个:

$string = "(731) some text here with number 2 (220) some 54 number other text here";
$a = preg_split('/\s(?=\()/', $string);//split by spaces preceding the left bracket
$res = array();
foreach($a as $v){
    $r = preg_split('/(?<=\))\s/', $v);//split by spaces following the right bracket
    if(isset($r[0]) && isset($r[1])){
        $res[trim($r[0],'() ')] = trim($r[1]);//trim brackets and spaces
    }
}
print_r($res);

输出:

Array
(
    [731] => some text here with number 2
    [220] => some 54 number other text here
)

演示

如果您只想限制在括号中有3位数字的数字上,只需修改环视:

$a = preg_split('/\s(?=\([0-9]{3}\))/', $string);

1
你可以尝试这个,
<?php
$str="(731) some text here (220) some other text here";
echo $str .'<br>';
$arr1=explode('(', $str);
$size_arr=count($arr1);
$final_arr=array();
for($i=1;$i<$size_arr; $i++){
    $arr2=explode(')', $arr1[$i]);
    $final_arr[$arr2[0]]=trim($arr2[1]);
}
echo '<pre>';
print_r($final_arr);
?>

使用此链接测试代码,点击这里。

我尝试使用简单的语法。希望大家都能理解。


1

也许你可以在 preg_split 中添加 PREG_SPLIT_DELIM_CAPTURE 标志。来自 preg_split 手册页面 (http://php.net/manual/en/function.preg-split.php)

PREG_SPLIT_DELIM_CAPTURE

如果设置了此标志,则定界符模式中的带括号表达式将被捕获并返回。

因此,如果您将代码更改为:

$results = preg_split('/\(([0-9]+)\)/s', $data,null,PREG_SPLIT_DELIM_CAPTURE);

您将获得类似于以下的数组:

Array
(
    [0] => KS/M/ 2013/1238 
    [1] => 220
    [2] =>  23/12/2013 
    [3] => 300
    [4] => 

    [5] => 731
    [6] =>  VALDETE BUZA ADEM JASHARI- PRIZREN, KS 
    [7] => 526
    [8] => 

    [9] => 591
    [10] => 

    [11] => 740
    [12] => 


    [13] => 540
    [14] =>  DEINA 
    [15] => 546
    [16] => 


    [17] => 511
    [18] =>  3 Preparatet për zbardhim dhe substancat tjera për larje rrobash; preparatet për pastrim, shkëlqim, fërkim dhe gërryerje; sapunët; parfumet, vajrat esencialë, preparatet kozmetike, losionet për flokë, pasta për dhembe
14 Metalet e cmueshme dhe aliazhet e tyre; mallrat në metale të cmueshme ose të veshura me to, që nuk janë përfshire në klasat tjera; xhevahirët, gurët e cmueshëm; instrumentet horologjike dhe kronometrike (për matjen dhe regjistrimin e kohës)
25 Rrobat, këpucët, kapelat
35 Reklamim, menaxhim biznesi; administrim biznesi; funksione zyre
)

你需要做的是循环遍历该数组,但在这种情况下忽略第一个元素:
$myArray = array();
$myKey = '';
foreach ($results as $k => $v) {
  if ( ($k > 0) && ($myKey == '')) {
    $myKey = $v;
  } else if ($k > 0) {
    $myArray[$myKey] = $v; 
    $myKey = '';
  }
}

编辑:此回答适用于:

$data ='KS/M/ 2013/1238 (220) 23/12/2013 (300)
(731) VALDETE BUZA ADEM JASHARI- PRIZREN, KS (526)
(591)
(740)

(540) DEINA (546)

(511) 3 Preparatet për zbardhim dhe substancat tjera për larje rrobash; preparatet për pastrim, shkëlqim, fërkim dhe gërryerje; sapunët; parfumet, vajrat esencialë, preparatet kozmetike, losionet për flokë, pasta për dhembe
14 Metalet e cmueshme dhe aliazhet e tyre; mallrat në metale të cmueshme ose të veshura me to, që nuk janë përfshire në klasat tjera; xhevahirët, gurët e cmueshëm; instrumentet horologjike dhe kronometrike (për matjen dhe regjistrimin e kohës)
25 Rrobat, këpucët, kapelat
35 Reklamim, menaxhim biznesi; administrim biznesi; funksione zyre';

1
我很确定定义键是不可能的,因为正则表达式会持续添加匹配项。 我会定义两个正则表达式, 一个用于键:
preg_match_all("/(\()([0-9]*)(\))\s/", $input_lines, $output_array);

你会在 $output_array[2] 中找到你的密钥。 还有一个文本(看起来差不多):
preg_split("/(\()([0-9]*)(\))\s/", $input_line);

之后,您可以通过迭代两个数组来构建自定义数组。 在插入时,请确保修剪第二个数组中的字符串。

1
使用preg_replace_callback()函数,您可以快速实现所需的功能(当只有括号中包含3个数字时):
$string = "(731) some text here with number 2 (220) some 54 number other text here";
$array = array();
preg_replace_callback('~(\((\d{3})\))(.*?)(?=(?1)|\Z)~s', function($match) use (&$array) {
    $array[$match[2]] = trim($match[3]);
}, $string);
var_dump($array);

输出:

array(2) {
  [731]=>
  string(28) "some text here with number 2"
  [220]=>
  string(30) "some 54 number other text here"
}

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