Bash脚本比较两个日期变量

23

我试图比较用户提供的日期和文件中的日期,这是一个文本文件,列出了许多日期和时间。

例如,用户会输入一个日期,如22/08/2007和1:00的时间,我需要脚本计算在用户提供的日期之后有多少个文本文件里的日期。

我通过将文本文件中的每个日期转换为Unix时间戳,然后进行比较来实现这一点。在bash中难道没有直接比较两个日期的方法吗?

谢谢您的帮助。


更多的信息:在文本文件中,日期被列为以下格式... 42.106.251.158 Wed Jul 11 22:57:57 GMT 2007。每个日期前都有一个IP地址。 - Xleedos
5个回答

19

GNU date命令可以将日期转换为自1970年以来的秒数。尝试运行此脚本:

#! /bin/bash
DATE=$(date -d "$3-$2-$1 01" '+%s')
COUNT=0
tr '/' ' ' | {
    while read D M Y ; do
    THIS=$(date -d "$Y-$M-$D 01" '+%s')
    if (( THIS > DATE )) ; then
        COUNT=$((COUNT + 1))
    fi
    done
    echo $COUNT
}

它期望三个参数和stdin中的原始日期:

for D in $(seq 19 25) ; do echo $D/08/2007 ; done | ./count.sh 22 08 2007
3

它将持续工作直到2038年。;-)


嗨,再次感谢您的快速回复。我已经使用日期将日期/时间转换为Unix时间代码,但还是谢谢您。它似乎有点冗长,我认为一定有更简单的方法! =)我想没有了。感谢大家的帮助。 - Xleedos

4
如果您不介意使用外部辅助工具,可以看一下我的dateutils。它已经覆盖了您的使用场景。
dgrep -i '%d/%m/%Y %H:%M' '>=2007-08-22 01:00:00' < FILE | wc -l

在这里,FILE是您的日期文件,-i指定了文件中使用的日期格式(我假设这里的日期格式为22/08/2007 01:00)。匹配的行将被打印出来,因此计数它们可以得到您想要的信息。


2

为什么不直接去掉单个数字,从最高位到最低位重新排列,将它们组合成一个新的大数,然后再进行比较呢? :) 假设在$1$2中都有一个日期,并且假设日期格式为dd-mm-yyyy(添加小时和分钟很容易):

d1=`echo "$1" | cut -d "-" -f 1`
m1=`echo "$1" | cut -d "-" -f 2`
y1=`echo "$1" | cut -d "-" -f 3`
date1="$y1$m1$d1"

d2=`echo "$2" | cut -d "-" -f 1`
m2=`echo "$2" | cut -d "-" -f 2`
y2=`echo "$2" | cut -d "-" -f 3`
date2="$y2$m2$d2"

if [ "$date1" -gt "$date2" ]; then
    #date1 > date2
else
    #date2 >= date1
fi

请注意,对于1位数字的字段,您需要使用零填充,例如,如下日期将起作用:
01-01-2013

而且这样的日期是不被允许的

1-1-2013

干杯 :-)


我喜欢这种技巧...你也可以使用awk将日期字符串重新格式化为数字,例如: date1=$(echo $1 | awk -F'-' '{$3$2$1}') 当然,你也可以对date2做同样的操作... 谢谢 EdoardoSchnell - cptHammer
好的解决方案是,如果获取值之间存在延迟,则比较两个日期的时代时间可能不准确。 - ibaralf

1
上述命令比较整数形式的日期,在比较同一年的日期时可以正常工作。更好的方法是将日期分解为dd、mm和yyyy三个部分,然后进行比较。就像下面这样:
sysdate=`date +%d%m%Y`
sys_dd=`echo $sysdate|cut -c1,2`
sys_mm=`echo $sysdate|cut -c3,4`
sys_yyyy=`echo $sysdate|cut -c5-8`


cd $dir_source #moving in directory where report are placed


for i in *.*       #reading all the files present in directory and comparing with current sysdate
do
filename=$i
filedate=`echo $filename| cut -d '_' -f1`
file_dd=`echo $filedate|cut -c1,2`
file_mm=`echo $filedate|cut -c3,4`
file_yyyy=`echo $filedate|cut -c5-8`


if [ $sys_yyyy -lt $file_yyyy ]
then
echo "future cob file, check for the error"elif [ $sys_yyyy -gt $file_yyyy ]
then
echo "prev cob file , to be removed"
else
     if [ $sys_mm -lt $file_mm ]
     then
     echo "future cob file, check for the error"
     elif [ $sys_mm -gt $file_mm ]
     then
     echo "prev cob file , to be removed"
     else

          if [ $sys_dd -lt $file_dd ]
          then
          echo "future cob file, check for the error"
          elif [ $sys_dd -gt $file_dd ]
          then
          echo "prev cob file , to be removed"
          else
          echo "file date is same is cob date, retaining the file as it is"
          fi
     fi
fi

1
问题在于日期的打印方式使得字符串比较时,"1/1/2050 1:00" < "2/1/1999 0:00"。而且,既然脚本无法自动识别日期时间格式,除非你明确指定,否则你就必须将任何日期转换为可进行比较的格式 - 要么按照重要程度排序(例如ISO日期),让最重要的元素(年份)放在前面等等,要么将其转换为数字。

你好,感谢快速回复。日期和时间的格式如下:Wed Jul 11 22:57:57 GMT 2007,用户输入也使用Date转换为该格式。是否有类似于Tests -ot/-nt的东西来比较两个日期? - Xleedos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接