如何使用perl/php/grep等从csv中提取日期范围?
有没有办法从下面这样的文本中(如果它已经在一个数组或者文件里)提取出指定日期范围内的行呢?
比如说,如果我想要提取从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
谢谢!
7 个回答
3
嗯,你可能可以用grep来搞定这个,但其实用sed更合适:
sort < file.csv | sed -ne /^2009-09-04/,/^2009-09-09/p
4
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
(这个解决方案是用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循环……或者使用array_filter
函数,这个函数就是为了这个目的而存在的;-)
比如,你可以用这样的代码:
$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
(或者根据格式进行一些自定义解析),然后再比较时间戳。
但是,在你的情况下……不需要那么复杂;-)