首页 > 解决方案 > PHP - 循环 CSV 文件并检查空行

问题描述

由于各种正则表达式,我正在尝试读取 csv 文件并提取数据。我无权访问导入的 csv 文件内容。

但是,可能有一行或多行是空的。为此,可以使用修剪函数()。问题是要知道如何调整我的各种数组来恢复空行

在此处输入图像描述

在这个例子中,电话号码有两行是空的,那么我该如何检测以及如何在我的电话数组中插入这些空行?

例如,如果我这样做:

foreach($fullNames as $fullName)
{
    echo $fullName."<br>";
}

foreach($phones as $phone)
{
    echo $phone."<br>";
}

结果将是:

{马克·瓦多,马克·瓦多,马克·瓦多,马克·瓦多,马克·瓦多}

{0692 10 10 10, 0692 10 10 10,0692 10 10 10}

我想要实现的是:

{马克·瓦多,马克·瓦多,马克·瓦多,马克·瓦多,马克·瓦多}

{0692 10 10 10, , 0692 10 10 10, , 0692 10 10 10}

$emptyValue = "";

if (($handle = fopen($loadedSheetName.'.csv', "r")) !== FALSE) 
{ 
    fgetcsv($handle);

    while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) 
    {   
        $col = count($data);

        for($c = 0; $c < $col; $c++)
        {
            $phones = array();
            $mails = array();
            $zipcodes = array();
            $fullNames = array();

            if ('' === trim($data[$c]))
            {
                $emptyValue = "";
            }

            if(preg_match('/^(0)(692|693|262)(\d{6})$/', $data[$c], $matches))
            {
                $phones[] = "+262".$matches[2].$matches[3];
            }

            if(preg_match('/^(0)(692|693|262)( )(\d{2})( )(\d{2})( )(\d{2})$/', $data[$c], $matches))
            {
                $phones[] = "+262".$matches[2].$matches[4].$matches[6].$matches[8];
            }

            if(preg_match('/^(0)(692|693|262)( )(\d{2})( )(\d{2})( )(\d{2})(\/)(0)(692|693|262)( )(\d{2})( )(\d{2})( )(\d{2})$/', $data[$c], $matches))
            {
                $phones[] = "+262".$matches[2].$matches[4].$matches[6].$matches[8].$matches[9]."+262".$matches[11].$matches[13].$matches[15].$matches[17];
            }

            if(preg_match('/^([^\W][a-zA-Z0-9_]+)(\.[a-zA-Z0-9_]+)*(\@)([a-zA-Z0-9_]+)*(\.[a-zA-Z]{2,4})$/', $data[$c], $matches))
            {
                $mails[] = $matches[0];
            } 

            if(preg_match('/^(Sainte|Saint|saint|sainte)(-)([a-zA-z]+)$/', $data[$c], $matches))
            {
                $zipcodes[] = $matches[0];
            }

            if(preg_match('/^(([a-zA-Z\W]+)( )([a-zA-Z\W]+))$/', $data[$c], $matches))
            {
                $fullNames[] = $matches[0];
            }

            if(preg_match('/^(([a-zA-Z\W]+)( )([a-zA-Z\W]+)( )([a-zA-Z\W]+))$/', $data[$c], $matches))
            {  
                $fullNames[] = $matches[0];
            }
        }
    }

    fclose($handle);
}

标签: phpregexcsv

解决方案


您在这里向我们展示的内容包含许多不良做法。当我们不知道问题是什么时,很难建议您应该如何解决问题;最终结果不是填充一些 php 数组——这些只是一种临时存储机制。

您的问题也有些令人困惑 - 与 CSV 文件相关的“行”描述了一条记录,一条记录由字段(或有时取决于 CSV 文件的性质的属性值)组成。根据您的叙述,您描述为“线”的是字段或属性值。

CSV 文件中的每条记录按其出现的行保留其组成字段之间的关联。但是,如果字段本身被引用或转义,则可以包含嵌入的换行符。

通过不将空白值填充到您的临时表示中,您正在打破这种关联。

我想要实现的是这个

所以你想保留空白值 - 不要跳过它们。所以在数组中添加一个空白值。

目前,您的代码结构非常糟糕且有缺陷。您只是将元素添加到不同数组的末尾 - 不仅您有空白字段的问题,而且如果您在添加条件时出错,您将失去非空白数据的数组同步。

结果将是:

不,不会的。每次您从文件中读取一行数据时,您向我们展示的代码都会重置输出数组。

如果你搬家

        $phones = array();
        $mails = array();
        $zipcodes = array();
        $fullNames = array();

在 while 循环之外,您将获得与您描述的内容接近的内容。

解决问题的正常方法是使用else if使您的每个匹配条件独占:

        if ('' === trim($data[$c]))
        {
            $emptyValue = "";
        }
        else if(preg_match('/^(0)(692|693|262)(\d{6})$/', $data[$c], $matches))
        {
            $phones[] = "+262".$matches[2].$matches[3];
        }
        else if if(preg_match('/^(0)(692|693|262)( )(\d{2})( )(\d{2})( )(\d{2})$/', $data[$c], $matches))
        {
            $phones[] = "+262".$matches[2].$matches[4].$matches[6].$matches[8];
        ...

但是您的代码当前是为了适应记录中以任何顺序显示的字段而编写的。虽然情况可能确实如此,但这是一种非常不寻常的情况,并且基于所有存在的字段(不是这种情况)并且不重复。如果您的输入文件缺乏结构,那么您就是在浪费时间编写代码来自动解析数据——即使您解决了这个问题,您也会遇到更多的痛苦。垃圾进垃圾出。

然而,作为一个纯粹的学术练习,如果我们接受隐含谓词被强制执行,那么解决它仍然是微不足道的。只需在您的代码中跟踪原始记录关联:

if (($handle = fopen($loadedSheetName.'.csv', "r")) !== FALSE) { 
  $phones = array();
  $mails = array();
  $zipcodes = array();
  $fullNames = array();
  $record=0;
  fgetcsv($handle);
  while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {   
    $record++;
    $col = count($data);
    for($c = 0; $c < $col; $c++) {
        if(preg_match('/^(0)(692|693|262)(\d{6})$/', $data[$c], $matches))
        {
           $phones[$record] = "+262".$matches[2].$matches[3];
        }
   ...

推荐阅读