【问题标题】:PHP Regex Multiple InstancesPHP 正则表达式多个实例
【发布时间】:2018-01-23 12:12:46
【问题描述】:

我目前正在导入 CSV 数据,需要将其全部整理好。

较小的示例数据如下。

"Name","Address"
"John Doe","5111 Fury Rd
Santa Cruz"
"Jane Doe","321 Tess St Texas"
"Josh Doe","653 1st St 
Orlando Florida
United States"

如您所见,我们需要在引号之外的换行符处进行拆分,因为 str_getcsv 不是多行的。

我最初使用过这个表达方式。

$lines = preg_split('/[\r\n]{1,2}(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/',$data);

但是当字符串中的字符数超过 XXXX 时,preg_split 就搞砸了。

所以目前使用 preg_match_all 但需要正则表达式选择器的问题。

preg_match_all('/^(.*?)[\r\n]{1,2}(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/', $data, $matches);

目前只匹配第一个实例。

Array(
    [0] => Array ( [0] => "Name","Address")
    [1] => Array ( [0] => "Name","Address")
)

有什么线索可以让它返回数组中的所有数据?

【问题讨论】:

  • 这是一串数据吗?
  • 我正在导入它的 CSV 数据,所以它应该是 1 个巨大的字符串,每个条目(行)用换行符分隔。
  • ^ 没有 m 修饰符只匹配第一行(字符串的开头)。
  • 你说得对。完全错过了!
  • 也许/^"([^"]+?)","([^"]+?)"$/m 对你有用?这也假设您的字符串永远不会在其中转义引号,并且您只有 2 个匹配项

标签: php regex csv preg-match-all preg-split


【解决方案1】:

如果你需要使用preg_match_all(),你可以尝试这个模式来创建一个匹配数组,然后将str_getcsv()映射到结果上;例如:

<?php

$csvString = <<<CSV
"Name","Address"
"John Doe","5111 Fury Rd
Santa Cruz"
"Jane Doe","321 Tess St Texas"
"Josh Doe","653 1st St
Orlando Florida
United States
CSV;


preg_match_all('/(.*)(?:\n)/m', $csvString, $csvRows);

$csvData = array_map(function ($csvRow) {
    return str_getcsv($csvRow);
}, $csvRows[1]);

print_r($csvData);

鉴于您的示例输入,这会产生:

Array
(
    [0] => Array
        (
            [0] => Name
            [1] => Address
        )

    [1] => Array
        (
            [0] => John Doe
            [1] => 5111 Fury Rd
        )

    [2] => Array
        (
            [0] => Santa Cruz"
        )

    [3] => Array
        (
            [0] => Jane Doe
            [1] => 321 Tess St Texas
        )

    [4] => Array
        (
            [0] => Josh Doe
            [1] => 653 1st St
        )

    [5] => Array
        (
            [0] => Orlando Florida
        )

)

希望这会有所帮助:)

【讨论】:

    【解决方案2】:

    这是解析它的一种方法。我已经注释掉了地址中删除新行的部分。如果你想要它,只需删除评论。

    $re = '/\"(.*?)\",\"(.*?)\"/s';
    $data = '"Name","Address"
    "John Doe","5111 Fury Rd
    Santa Cruz"
    "Jane Doe","321 Tess St Texas"
    "Josh Doe","653 1st St
    Orlando Florida
    United States"';
    
    preg_match_all($re, $data, $matches);
    
    /*
    foreach($matches[2] as &$value){
        $value = str_replace(PHP_EOL, " ", $value);
    }
    */
    var_dump($matches);
    

    https://3v4l.org/7kRDt

    foreach 的输出:

    array(3) {
      [0]=>
      array(4) {
        [0]=>
        string(16) ""Name","Address""
        [1]=>
        string(36) ""John Doe","5111 Fury Rd
    Santa Cruz""
        [2]=>
        string(30) ""Jane Doe","321 Tess St Texas""
        [3]=>
        string(53) ""Josh Doe","653 1st St
    Orlando Florida
    United States""
      }
      [1]=>
      array(4) {
        [0]=>
        string(4) "Name"
        [1]=>
        string(8) "John Doe"
        [2]=>
        string(8) "Jane Doe"
        [3]=>
        string(8) "Josh Doe"
      }
      [2]=>
      array(4) {
        [0]=>
        string(7) "Address"
        [1]=>
        string(23) "5111 Fury Rd Santa Cruz"
        [2]=>
        string(17) "321 Tess St Texas"
        [3]=>
        &string(40) "653 1st St Orlando Florida United States"
      }
    }
    

    【讨论】:

    • 感谢安德烈亚斯的回答。不幸的是,每行有 100 多列数据。这会将数据分成对。 IE。 [0]=>"First Name","Last Name" [1]=>"City","State"...等
    • @user1512593 然后只需添加适量的模式。您可以使用 for 循环构建模式。 '/\"(.*?)\",\"(.*?)\",\"(.*?)\"/s';
    • 谢谢。我认为重复 100 多次相同的事情是疯狂的谈话,但它的效果很好 Andreas。谢谢!
    • @user1512593 这不是我引以为豪的解决方案,但如果它有效......请记住,如果一个条目没有开头或结尾“它将惨遭失败
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 2017-06-03
    相关资源
    最近更新 更多