【问题标题】:Parse CSV file and match pattern in PHP在 PHP 中解析 CSV 文件并匹配模式
【发布时间】:2013-07-03 07:37:11
【问题描述】:

我有一个CSV文件如下

***Client Name: abc***,
,
# ----------------------------------------,
# Twitter : Mentions - Count,
# ----------------------------------------,
Date/Time (GMT),abc
6/6/2013,1
6/11/2013,3
6/12/2013,2
6/13/2013,1
6/14/2013,2
6/15/2013,4
6/17/2013,4
6/18/2013,8
6/19/2013,7
# *** Interval: Daily ***,
,
***Client Name: abc***,
,
# ----------------------------------------,
# Facebook Insights : Likes by Source,
# ----------------------------------------,
Sources,Likes
Mobile,3602
Page Profile,470
Recommended Pages,86
Ads,64
Like Story,49
Mobile Sponsored Page You May Like,44
Page Browser,33
Search,22
Timeline,16
Mobile Page Suggestions On Liking,15
3 more sources,48
,
***Client Name: xyz***,
,
# ----------------------------------------,
# Twitter : Mentions - Count,
# ----------------------------------------,
Date/Time (GMT),xyz
6/12/2013,1
# *** Interval: Daily ***,
,
***Client Name: pqr***,
,
# ----------------------------------------,
# Twitter : Mentions - Count,
# ----------------------------------------,
Date/Time (GMT),pqr
6/6/2013,2
6/7/2013,3
6/9/2013,6
6/10/2013,1
6/12/2013,4
6/13/2013,1
6/14/2013,9
6/15/2013,5
6/16/2013,1
6/18/2013,2
6/19/2013,2
# *** Interval: Daily ***,

我想从中提取 Twitter:提及 - 计算数据并将所有内容保存在数据库中。

我想要

之间的内容
# ----------------------------------------,
# Twitter : Mentions - Count,
# ----------------------------------------,

 # *** Interval: Daily ***,

如何在 PHP 中匹配此模式是否有任何 php 类与文件中的模式匹配,或者我如何使用 regax 来做到这一点。

我对模式匹配一​​无所知我刚刚尝试使用 fgetcsv() 作为读取 csv 文件

 $file = fopen($uploaded_file_path, 'r');
            echo "<pre>";
            while (($line = fgetcsv($file)) !== FALSE) {
              print_r($line);
            }
            fclose($file);

【问题讨论】:

标签: php regex pattern-matching fgetcsv


【解决方案1】:

说明

此正则表达式将找到每个部分标题 Twitter Mentions - Count 并将部分正文捕获到第 1 组。

^\#\sTwitter\s:\sMentions\s-\sCount,[\s\r\n]+    # match the header
^\#\s----------------------------------------,[\s\r\n]+   # match the separator line
(^(?:(?!\#\s\*\*\*\sInterval:\sDaily\s\*\*\*,).)*)    # match the rest of the string upto the first Interval Daily

展开

  • 第一部分简单地找到每个块的开头,它有很多字符,但基本上是直截了当的。

    • ^ 匹配一行的开头,需要多行选项,通常是 m
    • \#\sTwitter\s:\sMentions\s-\sCount, 匹配这个确切的字符串,注意\s 将匹配一个空格字符,我这样做是因为我喜欢使用通常为x 的忽略空格选项
    • [\s\r\n]+ 匹配一个或多个空格或换行符。
    • ^\#\s----------------------------------------,[\s\r\n]+ 这匹配分隔行中从行首 ^ 到末尾的换行符
  • 这个部分捕捉了部分的主体,是真正的魔法发生的地方。

    • (启动捕获组1
    • ^ 确保我们匹配行的开头,这确保下一个前瞻正确验证
    • (?: 启动非捕获组。这个非捕获组的构造在它遇到负前瞻内的不需要的字符串时会自行终止。这将最终捕获上面部分标题和结束字符串之间的每个字符。
    • (?! 开始否定前瞻,这将验证我们没有进入不需要的关闭文本,这标志着该部分的结束。
    • \#\s\*\*\*\sInterval:\sDaily\s\*\*\*, 匹配不需要的文本。如果找到了,那么负前瞻将失败
    • ) 关闭负面展望
    • . 匹配任何字符,这需要“点匹配新行”选项,通常是s
    • )关闭非捕获组
    • * 允许非捕获组重复零次或多次。
    • ) 关闭捕获组 1。由于此捕获组内发生的所有事情,每个匹配的 . 都将存储在这里。

PHP 示例

实时示例:http://www.rubular.com/r/stgaiBeSE1

示例文本

***Client Name: abc***,
,
# ----------------------------------------,
# Twitter : Mentions - Count,
# ----------------------------------------,
Date/Time (GMT),abc
6/6/2013,1
6/11/2013,3
6/12/2013,2
6/13/2013,1
6/14/2013,2
6/15/2013,4
6/17/2013,4
6/18/2013,8
6/19/2013,7
# *** Interval: Daily ***,
,
***Client Name: abc***,
,
# ----------------------------------------,
# Facebook Insights : Likes by Source,
# ----------------------------------------,
Sources,Likes
Mobile,3602
Page Profile,470
Recommended Pages,86
Ads,64
Like Story,49
Mobile Sponsored Page You May Like,44
Page Browser,33
Search,22
Timeline,16
Mobile Page Suggestions On Liking,15
3 more sources,48
,
***Client Name: xyz***,
,
# ----------------------------------------,
# Twitter : Mentions - Count,
# ----------------------------------------,
Date/Time (GMT),xyz
6/12/2013,1
# *** Interval: Daily ***,
,
***Client Name: pqr***,
,
# ----------------------------------------,
# Twitter : Mentions - Count,
# ----------------------------------------,
Date/Time (GMT),pqr
6/6/2013,2
6/7/2013,3
6/9/2013,6
6/10/2013,1
6/12/2013,4
6/13/2013,1
6/14/2013,9
6/15/2013,5
6/16/2013,1
6/18/2013,2
6/19/2013,2
# *** Interval: Daily ***,

代码

<?php
$sourcestring="your source string";
preg_match_all('/^\#\sTwitter\s:\sMentions\s-\sCount,[\s\r\n]+
^\#\s----------------------------------------,[\s\r\n]+
(^(?:(?!\#\s\*\*\*\sInterval:\sDaily\s\*\*\*,).)*)/imsx',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>

捕获组 1 的匹配项

[0] => Date/Time (GMT),abc
    6/6/2013,1
    6/11/2013,3
    6/12/2013,2
    6/13/2013,1
    6/14/2013,2
    6/15/2013,4
    6/17/2013,4
    6/18/2013,8
    6/19/2013,7

[1] => Date/Time (GMT),xyz
    6/12/2013,1

[2] => Date/Time (GMT),pqr
    6/6/2013,2
    6/7/2013,3
    6/9/2013,6
    6/10/2013,1
    6/12/2013,4
    6/13/2013,1
    6/14/2013,9
    6/15/2013,5
    6/16/2013,1
    6/18/2013,2
    6/19/2013,2

            )

【讨论】:

  • 你太棒了太棒了,你能解释一下你用哪些步骤找到这个正则表达式,你是如何创建那个图像的。
  • :) 从技术上讲,我在运行它之前在 Windows 记事本中编写了它,然后通过该实时示例运行它。对于我使用 debuggex.com 的图像。尽管它不支持lookbehinds、命名捕获组或原子组,但它对于理解表达式流仍然很方便。还有 regexper.com。它们也做得很好,但在您输入时并不是实时的。
  • 我用表达式的详细扩展解释更新了答案,享受。
  • @RoYoMi 谢谢你的回答你能告诉我什么是 $sourcestring="your source string";
  • @BKarthikKumar 我选择将源文本分离到原始答案中的一个部分。源文本本身看起来像编程代码,我觉得将其嵌入示例代码可能会造成混淆。
【解决方案2】:

试试这个

public static function csv_to_array($filename='', $delimiter=',')
 { 
    if(!file_exists($filename) || !is_readable($filename))
        return FALSE;

    $header = NULL;
    $data = array();
    if (($handle = fopen($filename, 'r')) !== FALSE)
    {
        while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
        {
                $data[] = $row;
        }
        fclose($handle);
    }
    return $data;
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-19
    • 2011-04-25
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    相关资源
    最近更新 更多