【问题标题】:How do I extract a date range from a csv using perl/php/grep/etc?如何使用 perl/php/grep/etc 从 csv 中提取日期范围?
【发布时间】:2010-11-25 01:16:12
【问题描述】:

有没有办法获取如下文本(如果它已经在数组或文件中)并让它在指定日期范围内删除行?

例如,如果我希望从 2009 年 9 月 4 日到 2009 年 9 月 9 日的每一行都被拉出(也许这可以用 grep 完成?)我该怎么做呢?

date,test,time,avail
2009-09-01,JS,0.119,99.90
2009-09-02,JS,0.154,99.89
2009-09-03,SWF,0.177,99.90
2009-09-04,SWF,0.177,99.90
2009-09-05,SWF,0.177,99.90
2009-09-06,SWF,0.177,99.90
2009-09-07,SWF,0.177,99.90
2009-09-08,SWF,0.177,99.90
2009-09-09,SWF,0.177,99.90
2009-09-10,SWF,0.177,99.90

谢谢!

【问题讨论】:

    标签: php python ruby perl grep


    【解决方案1】:

    Python

    import csv
    import datetime
    
    start= datetime.datetime(2009,9,4)
    end= datetime.datetime(2009,9,9)
    
    source= csv.DictReader( open("someFile","rb") )
    for row in source:
        dt = datetime.datetime.strptime(row['date'],"%Y-%m-%d")
        if start <= dt <= end:
            print row # depends on what "pulled out" means
    

    【讨论】:

      【解决方案2】:

      嗯,你也许可以以某种方式使它与 grep 一起工作,但 sed 更适合这项任务:

      sort < file.csv | sed -ne /^2009-09-04/,/^2009-09-09/p
      

      【讨论】:

        【解决方案3】:

        (这个解决方案是用 PHP 编写的——但我想你可以直接从命令行使用 grep 或任何东西)

        考虑到您的日期采用YYYY-MM-DD 格式,并且它们位于每行的开头,您只需按字母顺序比较各行即可比较日期。

        一种解决方案是:

        • 加载字符串
        • 逐行分解
        • 删除第一行
        • 遍历行,只保留您感兴趣的行

        对于第一部分:

        $str = <<<STR
        date,test,time,avail
        2009-09-01,JS,0.119,99.90
        2009-09-02,JS,0.154,99.89
        2009-09-03,SWF,0.177,99.90
        2009-09-04,SWF,0.177,99.90
        2009-09-05,SWF,0.177,99.90
        2009-09-06,SWF,0.177,99.90
        2009-09-07,SWF,0.177,99.90
        2009-09-08,SWF,0.177,99.90
        2009-09-09,SWF,0.177,99.90
        2009-09-10,SWF,0.177,99.90
        STR;
        $lines = explode(PHP_EOL, $str);
        unset($lines[0]); // first line is useless
        

        并且,要遍历行,过滤出/过滤出您想要/不想要的内容,您可以使用 foreach 循环... /p>

        例如,你可以使用这样的东西:

        $new_lines = array_filter($lines, 'my_filter');
        var_dump($new_lines);
        

        你的回调函数是:

        function my_filter($line) {
            $min = '2009-09-04';
            $max = '2009-09-09';
            if ($line >= $min && $line <= $max) {
                return true;
            } else {
                return false;
            }
        }
        

        结果:

        array
          4 => string '2009-09-04,SWF,0.177,99.90' (length=26)
          5 => string '2009-09-05,SWF,0.177,99.90' (length=26)
          6 => string '2009-09-06,SWF,0.177,99.90' (length=26)
          7 => string '2009-09-07,SWF,0.177,99.90' (length=26)
          8 => string '2009-09-08,SWF,0.177,99.90' (length=26)
        

        希望这会有所帮助;-)


        如果您的日期不是YYYY-MM-DD 格式,或者不在每一行的开头,您必须explode 行,并使用strtotime (或进行一些自定义解析,具体取决于格式),然后比较时间戳。

        但是,在你的情况下......不需要所有这些;-)

        【讨论】:

        • 太棒了,正是我想要的!
        【解决方案4】:

        awk 解决方案类似于 sed:

        awk '/^2009-09-04/,/^2009-09-09/ {next} {print}' filename
        

        无需硬编码日期:

        awk -v start='^2009-09-04' -v stop='^2009-09-09' '
            $0 ~ start, $0 ~ stop {next}
            {print}
        ' date.data
        

        【讨论】:

          【解决方案5】:

          您可以使用perl's flip flop 提取行范围。

          【讨论】:

            【解决方案6】:

            使用R

            > d <- read.csv("http://dpaste.com/88980/plain/", sep=",", header=T)
            > r1 <- rownames(d[d$date == "2009-09-04",])
            > r2 <- rownames(d[d$date == "2009-09-09",])
            > d[rownames(d) %in% r1:r2,]
                    date test  time avail
            4 2009-09-04  SWF 0.177  99.9
            5 2009-09-05  SWF 0.177  99.9
            6 2009-09-06  SWF 0.177  99.9
            7 2009-09-07  SWF 0.177  99.9
            8 2009-09-08  SWF 0.177  99.9
            9 2009-09-09  SWF 0.177  99.9
            >
            

            【讨论】:

            • 你看到 R 标签了吗?你看到一个被接受的答案吗?您知道这个问题以及除您之外的所有答案的年龄吗?
            【解决方案7】:

            Perl:

            perl -F/,/ -ane '
                print if $F[0] ge "2009-09-04"
                      && $F[0] le "2009-09-09"' filename
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-07-28
              • 1970-01-01
              • 2015-07-24
              • 1970-01-01
              • 2023-03-31
              • 2020-07-29
              • 1970-01-01
              相关资源
              最近更新 更多