【问题标题】:Filter a CSV file using php使用 php 过滤 CSV 文件
【发布时间】:2014-06-11 11:17:46
【问题描述】:

我每天两次通过 ftp 传送 csv 文件。我正在尝试编写一个 php 文件来打开此文件,按类别列对其进行过滤,删除其中没有特定术语/术语的行,然后保存文件。

我已经尝试了许多在互联网上找到的 sn-ps 代码变体,但我终其一生都无法弄清楚如何让它发挥作用。

我尝试使用在这个问题中找到的代码变体,但无法使其在我的场景中工作

Filter a csv file by a word or text using php

如果它有助于我尝试编辑的 csv 文件位于此处: http://accurateav.co.uk/sahara/saharafeed.csv

<?php
$file  = fopen('saharafeed.csv', 'r');

// You can use an array to store your search words, makes things more flexible.
// Supports any number of search words.
$words = array('casio');    
// Make the search words safe to use in regex (escapes special characters)
$words = array_map('preg_quote', $words);
$regex = '/'.implode('|', $words).'/i';

while (($line = fgetcsv($file)) !== FALSE) {  
    list($ExportDate, $ItemCode, $Manufacturer, $Model, $ProductName, $DealerPrice, $Stock, $RRP, $Category, $ShortDesc, $LongDesc, $Weightkg, $EAN, $NonStock, $LargePictureURL, $SpecSheet, $HiResPhoto1, $HiResPhoto2) = $line;

    if(preg_match($regex, $Category)) {
        echo "$ExportDate, $ItemCode, $Manufacturer, $Model, $ProductName, $DealerPrice, $Stock, $RRP, $Category, $ShortDesc, $LongDesc, $Weightkg, $EAN, $NonStock, $LargePictureURL, $SpecSheet, $HiResPhoto1, $HiResPhoto2<br />\n";
    }
}

?>

这是迄今为止我用来过滤类别以仅显示卡西欧类别中的产品的代码,但是当我运行脚本时,即使卡西欧类别下有许多产品,也没有显示任何结果。

【问题讨论】:

  • 好吧,我们希望看到一些尝试和一些关于什么不起作用以及为什么不起作用的描述。这样,任何人都可以提交一份完整的申请,但也可能无法正常工作。不是很有帮助。
  • 但与其考虑“过滤”和“删除”行,也许您可​​以生成第二个文件。遍历第一个文件,仅将要保留的行复制到第二个文件中。之后,删除源文件并重命名目标文件。等等,
  • @GolezTrol 我已经修改了我的原始问题,以包含我目前用于执行过滤部分的代码。
  • 您确定卡西欧确实在类别栏中吗?我检查了你的 csv,似乎 casio 总是属于制造商列(即第 3 列)
  • 那是我现在感觉很愚蠢!

标签: php fopen fclose


【解决方案1】:

我认为您搜索错误的列。 casio 在制造商列内。您必须改为在那里搜索。考虑这个例子:

$i = 0;
$manufacturer_key = null;
$needles = array('casio', 'nec', 'hitachi');
$results = array();
$columns = array();
if(($handle = fopen('saharafeed.csv', 'r')) !== false) {
    while(($data = fgetcsv($handle, 4096, ',')) !== false) {
        if($i == 0)  {
            // sets the key where column to search
            $columns = $data;
            $i++; $manufacturer_key = array_search('Manufacturer', $data);
        } else {
            foreach($needles as $needle) {
                if(stripos($data[$manufacturer_key], $needle) !== false) {
                    $results[] = $data;
                } 
            }   
        }
    }
    fclose($handle);
}

array_unshift($results, $columns);

echo '<pre>';
print_r($results);
echo '</pre>';

casio 的示例输出:

Array
(
    [0] => Array
        (
            [0] => ExportDate
            [1] => ItemCode
            [2] => Manufacturer
            [3] => Model
            [4] => ProductName
            [5] => DealerPrice
            [6] => Stock
            [7] => RRP
            [8] => Category
            [9] => ShortDesc
            [10] => LongDesc
            [11] => Weightkg
            [12] => EAN
            [13] => NonStock
            [14] => LargePictureURL
            [15] => SpecSheet
            [16] => HiResPhoto1
            [17] => HiResPhoto2
        )

    [1] => Array
        (
            [0] => 11/06/2014
            [1] => 1610044
            [2] => NEC
            [3] => 60003221
            [4] => NEC  NP14ZL
            [5] => 999
            [6] => 0
            [7] => 1348.65
            [8] => Projectors Accessories
            [9] => 2.97-4.79:1 Zoom Lens
            [10] => Replacement 2.97–4.79:1 Zoom Lens compatible with the following products:

... and many more

将结果放回csv格式:

$fp = fopen('file.csv', 'w');

foreach ($results as $row) {
    fputcsv($fp, $row);
}

fclose($fp);

【讨论】:

  • 如果我想保存仅包含使用 Casio 找到的结果的文件,我该怎么做?所以它打开原始文件,搜索卡西欧然后以相同的格式保存原始文件,但只包含那些?例如,如果我想包括 NEC,我可以将其添加到针头中吗?或者这需要重新编码吗?基本上我只想设置它,以便它搜索预定义的制造商并将它们留在文件中,从而过滤原始表(如果有意义的话)
  • @Danny 您的意思是创建了另一个仅包含 casio 条目的 csv 吗?在我的示例中,我使用 $results 作为所有 casio 条目的容器。您可以使用 $results 并将其保存在另一个 csv 中。使用fputcsv
  • 抱歉编辑了我最初的评论以进一步解释我的意思,基本上我试图从供应商那里获取信息并过滤掉制造商不想要的产品,所以要么覆盖原始文件使用过滤后的数据或在与原始文件相同的 csv 结构中创建一个新文件
  • @Danny 所以在这种特殊情况下,casio 只是一个例子?如果您想要另一组值,只需将array_search() 中的字符串更改为您想要的另一个列名,并更改您想要搜索的$needle,就结构而言,它基本上仍然是同样,它只是过滤,创建新副本要好得多。
  • 是的,在这种情况下,casio 只是我要搜索的制造商之一,搜索词始终是制造商。我可以在同一个“查询”中搜索(例如)卡西欧、NEC、日立吗?
【解决方案2】:
Remove the line matching by a regular expression (by eliminating one containing digital   characters, at least 1 digit, located at the end of the line):

sed '/[0-9/][0-9]*$/d' 文件名.txt

【讨论】:

  • 对不起,我有点不清楚我要删除/替换什么,我对 PHP 比较陌生
  • 它基本上是 linux 命令,我希望你的服务器是 linux env。在这里你可以得到一个想法 - en.kioskea.net/faq/…
  • 这将放在文件中的什么位置?
  • 代码运行良好。它返回您在 Array $words = array('Cables'); 中选择的元素
  • 感谢上面的评论,我意识到我犯了一个错误并且在错误的列下进行搜索。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
  • 2020-03-31
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 2011-09-20
  • 2012-08-22
相关资源
最近更新 更多