【问题标题】:Extract part of string matching pattern提取部分字符串匹配模式
【发布时间】:2011-12-10 19:12:43
【问题描述】:

我想使用 PHP 扫描一大段文本并找到一个模式的所有匹配项,然后还要找到匹配项上方的 2 行和下方的 2 行。

我的文字看起来像这样,但在这个示例的上方和下方有一些额外的不必要的文字:

1

说明文字

123.456.12

10.00

10.00

3

不同的描述文本

234.567.89

10.00

30.00

#一些不需要的页脚文本,每个文本文件都会改变#

15

更多描述文字

564.238.02

4.00

60.00

15

更多描述文字

564.238.02

4.00

60.00

#一些不需要的页脚文本,每个文本文件都会改变#

15

更多描述文字

564.238.02

4.00

60.00

15

更多描述文字

564.238.02

4.00

60.00

使用 PHP,我希望以粗体匹配每个数字(总是相同的格式 - 3 个数字、点、3 个数字、点、2 个数字),然后还返回前 2 行和接下来 2 行,并希望返回一个数组以便我可以使用:

$contents[$i]["qty"] = "1";
$contents[$i]["description"] = "Description text";
$contents[$i]["price"] = "10.00";
$contents[$i]["total"] = "10.00";

等等……

这可能吗?我会使用正则表达式吗?任何帮助或建议将不胜感激!

谢谢

vzwick 回答

这是我使用的最终代码:

$items_array = array();
$counter = 0;

if (preg_match_all('/(\d+)\n\n(\w.*)\n\n(\d{3}\.\d{3}\.\d{2})\n\n(\d.*)\n\n(\d.*)/', $text_file, $matches)) {

    $items_string = $matches[0];
    foreach ($items_string as $value){

        $item = explode("\n\n", $value);

        $items_array[$counter]["qty"] = $item[0];
        $items_array[$counter]["description"] = $item[1];
        $items_array[$counter]["number"] = $item[2];
        $items_array[$counter]["price"] = $item[3];
        $items_array[$counter]["total"] = $item[4];

        $counter++;

    }

}
else
{
    die("No matching patterns found");
}

print_r($items_array);

【问题讨论】:

  • 总是5行的块吗?
  • 在我发布的示例上方和下方会有其他文本,但在项目循环中,它将始终是 5 行的块。
  • 此外,粗体数字将始终采用相同的格式 - 3 个数字、点、3 个数字、点、2 个数字
  • 我也刚刚意识到,虽然在项目循环中它始终是 5 行的块,但文本文件可以跨越多个页面,因此有一个我需要忽略的页脚。这就是为什么我想知道您是否可以匹配粗体数字然后收集它,然后将忽略前两行和后两行作为其他文本。

标签: php regex string multidimensional-array


【解决方案1】:
(.)+\n+(.)+\n+(\d{3}\.\d{3}\.\d{2})\n+(.)+\n+(.)+

可能需要将 \n 替换为 \r\n。确保正则表达式处于“。”时的模式。与换行符不匹配。

要按名称引用组,请使用命名捕获组:

(?P<name>regex)

example 的命名捕获组。

【讨论】:

    【解决方案2】:
    $filename = "yourfile.txt";
    $fp = @fopen($filename, "r");
    if (!$fp) die('Could not open file ' . $filename);
    
    $i = 0; // element counter
    $n = 0; // inner element counter
    
    $field_names = array('qty', 'description', 'some_number', 'price', 'total');
    $result_arr = array();
    
    while (($line = fgets($fp)) !== false) {
        $result_arr[$i][$field_names[$n]] = trim($line);
        $n++;
        if ($n % count($field_names) == 0) {
            $i++;
            $n = 0;
        }
    }
    
    fclose($fp);
    print_r($result_arr);
    

    编辑:那么,正则表达式。

    $filename = "yourfile.txt";
    $file_contents = @file_get_contents($filename);
    if (!$file_contents) die("Could not open file " . $filename . " or empty file");
    if (preg_match_all('/(\d+)\n\n(\w.*)\n\n(\d{3}\.\d{3}\.\d{2})\n\n(\d.*)\n\n(\d.*)/', $file_contents, $matches)) {
        print_r($matches[0]);
        // do your matching to field names from here ..
    }
    else
    {
        die("No matching patterns found");
    }
    

    【讨论】:

    • 抱歉,编辑了我的帖子说在我发布的示例上方和下方的文本文件中也会有其他文本。我不需要这个,所以需要忽略它。
    • 但是您的数据都在一个块中,对吗?有分隔符吗?
    • 不,抱歉,我本来是想发这个的。我将更新我的示例文本,向您展示会发生什么...
    • 谢谢,但刚刚尝试了您的代码,它为我发布的示例返回“未找到匹配模式”。
    • *sigh* 你的行是用双换行符分隔的吗?如果是,请检查更新。
    【解决方案3】:

    您可以将文件加载到一个数组中,然后他们使用 array_slice 对每 5 行块进行切片。

    <?php
    
    $file = file("myfile");
    $finalArray = array();
    
    for($i = 0; $i < sizeof($file); $i = $i+5)
    {
        $finalArray[] = array_slice($file, $i, 5); 
    }
    
    print_r($finalArray);
    ?>
    

    【讨论】:

    • 谢谢,但请参阅我更新的示例和 cmets,文件中会有我不需要的其他文本,因此我只想匹配粗体数字模式然后得到前 2 行和后 2 行
    猜你喜欢
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-22
    • 1970-01-01
    • 2021-08-05
    • 2019-03-20
    相关资源
    最近更新 更多