PHP-循环CSV文件并检查空行

时间:2019-04-05 10:44:00

标签: php regex csv

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

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

enter image description here

在此示例中,电话号码的两行为空,那么如何检测到该行以及如何在电话阵列中插入这些空行?

例如,如果我这样做:

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

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

结果将是:

{Marc Vador,Marc Vador,Marc Vador,Marc Vador,Marc Vador}

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

我要实现的目标是:

{Marc Vador,Marc Vador,Marc Vador,Marc Vador,Marc Vador}

{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);
}

1 个答案:

答案 0 :(得分:1)

您在此处向我们展示的内容包含许多不良做法。当我们不知道问题是什么时,很难建议您应该如何解决该问题。最终结果不是填充一些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];
        }
   ...