Nasıl perl / php / grep / etc kullanarak bir CSV bir tarih aralığı ayıklamak?

7 Cevap php

(Bu bir dizi ya da bir dosya zaten varsa) gibi aşağıda metni almak ve belirli bir tarih aralığı ile satırları şerit olması için bir yolu var mı?

I 2009-09-04 dan 2009-09-09 (belki bu grep ile yapılabilir?) Dışarı çekilmesine kadar her satırı istedim Örneğin nasıl öyle yapıyor hakkında gitmek istiyorsunuz?

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

Teşekkürler!

7 Cevap

(This solution is in PHP -- but you can probably do that directly from the command-line, I suppose, with somekind of grep or anything)

Lütfen tarihleri ​​YYYY-MM-DD biçiminde ve bunlar her satırın başında olduğu, sadece tarihleri ​​karşılaştırmak için alfabetik satırları karşılaştırmak zorunda göz önüne alındığında.

: Bir çözüm olacaktır

  • dize yüklenemedi
  • hatlarla patlayabilir
  • ilk satırı kaldırın
  • Eğer sadece bu o ilgi tutarak, çizgileri üzerinde yineleme

İlk parçalar için:

$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

Ve, / isteyenler istemiyorum / çıkış filtreleme, hatları üzerinde yineleme, bir foreach döngüsü kullanabilirsiniz ... Ya da sadece için var array_filter işlevini kullanabilirsiniz Bu ;-)

Örneğin, bu gibi bir şey kullanabilirsiniz:

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

Ve geri arama fonksiyonu olacaktır:

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

Ve, sonuç:

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)

Umarım bu yardımcı olur ;-)


If your dates where not in the YYYY-MM-DD format, or not at the beginning of each line, you'd have to
explode the lines, and use strtotime (or do some custom parsing, depending on the format), and, then, compare timestamps.

Ama, senin durumunda ... Tüm bu gerek yok ;-)

Piton

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

Evet, muhtemelen somehow bu grep ile iş yapmak, ancak sed görev için daha uygundur:

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

awk çözüm sed benzer:

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

Tarihleri ​​hardcoding olmadan:

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

Sen perl's flip flop bir çizgi dizi ayıklamak için kullanabilirsiniz.

Kullanma 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
>

Perl:

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