我有一个 csv,需要删除所有超过 7 天的行。这是csv的格式
人员 ID VIP CS SS LT FTLT PS 修改日期戳 T001028 1 1 1 0 0 0 05-07-2013 T001250 1 1 1 0 0 0 08-05-2012 T001261 1 1 1 0 0 1 04-04-2013 T001345 1 1 1 0 0 0 04-03-2013 T078503 1 1 1 0 0 0 04-03-2013 T079819 1 1 1 0 0 1 3/22/2013 T080119 1 1 1 0 0 1 04-02-2013 T090574 1 1 1 0 0 0 11/15/2012 T091106 1 1 1 0 0 1 3/22/2013
修改日期列的格式是 MM/DD/YYYY - 任何想法....希望在 RedHat 5 Linux 机器上执行某些操作。
答案1
tail
这是使用、date -d ...
、awk
以及 Bash 功能的方法。
tail -n+2 file.csv | {
while read line ; do
tmstmp=$(echo "$line" | awk '{print $8}');
[ $(( $(date -d "now" +%s) - $(date -d "$tmstmp" +%s) )) -lt $(( 60*60*24*7 )) ] && echo "$line";
done;
}
怎么运行的?
上面的代码解析了文件 中的行,file.csv
并获取第 8 列(日期),然后计算自纪元以来的秒数与解析的日期之间的增量。如果它们少于 7 天的秒数,则会打印该行。
调试
您可以放入这一行来调试正在发生的事情。将其放在该tmpstmp=...
行之后:
echo "TMSTMP: $tmstmp" "TMDELTA: $(( $(date -d "now" +%s) - $(date -d "$tmstmp" +%s) ))" "TMWINDOW: $(( 60*60*24*7 ))"
例子
为简单起见,我将上述内容放入脚本中并命名为rprttime.bash
:
#!/bin/bash
tail -n+2 file.csv | {
while read line ; do
tmstmp=$(echo "$line" | awk '{print $8}');
echo "TMSTMP: $tmstmp" "TMDELTA: $(( $(date -d "now" +%s) - $(date -d "$tmstmp" +%s) ))" "TMWINDOW: $(( 60*60*24*7 ))"
[ $(( $(date -d "now" +%s) - $(date -d "$tmstmp" +%s) )) -lt $(( 60*60*24*7 )) ] && echo "$line";
done;
}
现在当我们运行它时:
$ ./rprttime.bash
TMSTMP: 05/07/2013 TMDELTA: 5157421 TMWINDOW: 604800
TMSTMP: 08/05/2012 TMDELTA: 28917421 TMWINDOW: 604800
TMSTMP: 04/04/2013 TMDELTA: 8008621 TMWINDOW: 604800
TMSTMP: 04/03/2013 TMDELTA: 8095021 TMWINDOW: 604800
TMSTMP: 04/03/2013 TMDELTA: 8095021 TMWINDOW: 604800
TMSTMP: 3/22/2013 TMDELTA: 9131821 TMWINDOW: 604800
TMSTMP: 04/02/2013 TMDELTA: 8181421 TMWINDOW: 604800
TMSTMP: 11/15/2012 TMDELTA: 20101021 TMWINDOW: 604800
TMSTMP: 3/22/2013 TMDELTA: 9131821 TMWINDOW: 604800
如果将时间窗口从 7 天更改为 60 天并禁用调试行,您将看到打印一些行:
$ date
Fri Jul 5 16:49:19 EDT 2013
$ ./rprttime.bash
T001028 1 1 1 0 0 0 05/07/2013
答案2
另一个有限分叉的答案
由于有很多叉子鞭打出来,有一个巴什执行此操作的方法sed
仅使用 1 个叉子/bin/date
:
sedstr=""
{
i=1;
read now;
while read line;do
((i++));
[ $(( (now-line) /86400 )) -gt 143 ] && sedstr="${i}d;$sedstr"
done
}< <(
sed -ne $'s/^.*[ \t,]//g;y|-|/|;/[0-9]$/p;1inow' < file.tsv |
date -f - +%s
)
sed -e "$sedstr" < file.tsv
Person ID VIP CS SS LT FTLT PS Modified Datestamp
T001028 1 1 1 0 0 0 05-07-2013
T001261 1 1 1 0 0 1 04-04-2013
T001345 1 1 1 0 0 0 04-03-2013
T078503 1 1 1 0 0 0 04-03-2013
最后一个sed
命令可以用于-i
就地修改,而不是输出到控制台。
echo $sedstr
10d;9d;8d;7d;3d;
sed -e $sedstr -i file.tsv
cat file.tsv
Person ID VIP CS SS LT FTLT PS Modified Datestamp
T001028 1 1 1 0 0 0 05-07-2013
T001261 1 1 1 0 0 1 04-04-2013
T001345 1 1 1 0 0 0 04-03-2013
T078503 1 1 1 0 0 0 04-03-2013
答案3
如果您计算在调用 awk 之前应忽略这些行的日期,那么您可以执行以下操作:
awk -v cmpdate=20130628 '{line=$0; dateval=$8;FS="/"; $0=dateval;
thisdate=$3*10000+$1*100+$2; if (thisdate>cmpdate) print line; FS=" ";}' file
编辑1:
FS
最后重置为原始值。我只用一行输入测试了我的代码,因此它没有产生任何影响......
答案4
我将使用 Perl 执行此操作(从终端运行):
$ perl -lane 'BEGIN{$date=`date +%s`; chomp($date)}
if($.==1){print}
else{
$F[$#F]=~s/-/\//g;
$fdate=`date -d "$F[$#F]" +%s`;
chomp($fdate);
print if $date-$fdate<604800;
}' file.csv
该脚本的工作原理是计算今天的日期自纪元以来的秒数,然后将每行的日期转换为相同的格式,从今天的日期中减去它,并仅在小于 7 天的情况下打印 (7*24*60*60=604800)。
笔记
该脚本在几秒钟内运行,这对于您的想法来说可能有点过于精确。如果是这样,请告诉我,我会将其修改为在天级别上工作。
我也在动态转换
MM-DD-YYYY
,MM/DD/YYYY
如果您的输入文件是同构格式的,这可能不是必需的,但您发布的示例需要它。