删除 csv 文件中超过 7 天的行

删除 csv 文件中超过 7 天的行

我有一个 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-YYYYMM/DD/YYYY如果您的输入文件是同构格式的,这可能不是必需的,但您发布的示例需要它。

相关内容