如何在shell中管理日期

时间:2011-09-23 14:21:25

标签: bash shell unix date

我有一个包含14000个日期的文件。我写了一个脚本来找到最近5天,

26/03/2002:11:52:25
27/03/2002:11:52:25
29/03/2002:11:30:41
30/03/2002:11:30:41
26/03/2002:11:30:41
02/04/2002:11:30:41
03/04/2002:11:30:41
04/04/2002:11:30:41
05/04/2002:11:52:25
06/04/2002:11:52:25

假设这是文件,现在我的日期为02/04/2002:11:30:41作为输出。我想把日期从02/04/2002直到文件末尾的另一个文件。

start-date = 02/04/2002 (this is my start date) 
while [start-date lt end-date] do (while start date is less than end date )
start-date++ ( add one day to start day so if its 2/4/2002 it will become 3/4/2002)
echo $start-date|tee -a file1  (put it in a file)

此代码假设这样做但它有问题!为什么?

grep -n $SDATE thttpd.log | cut -d: -f1 (pattern=$SDATE)
sed '/$SDATE/=' thttpd.log
awk '/$SDATE/{ print NR }' thttpd.log
$ sed -n "$(awk '$SDATE/ { print NR }' input),$ p" thttpd.log
$ awk 'NR >= line_number' line_number=$(grep -n $SDATE -m 1 thttpd.log | cut -d: -f1) thttpd.log

6 个答案:

答案 0 :(得分:2)

假设文件按日期时间排序:

 sed -n '\.^02/04/2002.,$p' dates.list > results.list

从以02/04/2002开头的第一行打印到文件末尾。

答案 1 :(得分:0)

我自己没有使用它,但gawk命令(GNU的AWK)能够manipulate date/time strings。而且,gawk是awk命令的Linux版本。

您还可以将整个程序重写为单个awk脚本。这可能会让事情变得容易多了。请记住,awk是一种完整的编程语言,只需假定文件的读取循环并处理文件的每一行。

答案 2 :(得分:0)

以编程方式,您可以像这样找到第5天:

startdate=$( cut -d: -f1 filename | sort -u -t/ -k3 -k2 -k1 | tail -5 | head -1 )

然后,您可以打印大于或等于这一天的所有日期:

awk -F: -v start="$startdate" '
  BEGIN { split(start, s, "/"); sdate=s[3] s[2] s[1] } 
  { split($1, d, "/");  if (d[3] d[2] d[1] >= sdate) print }
' filename

答案 3 :(得分:0)

awk -F"/|:" '{print $3$2$1}' File_Name|sort -u| tail -5

答案 4 :(得分:0)

我写了一整套工具(dateutils)来解决这些问题。在你的情况下,它只是:

dgrep -i '%d/%m/%Y:%H:%M:%S' '>=02/04/2002:11:30:41' < FILE

其中-i选项指定输入格式,>=02/04/2002:11:30:41是您的截止日期(>=表示日期小于当前指定的日期)。

答案 5 :(得分:-1)

这是你想要的吗?

#!/bin/bash
# presumes GNU date

# input date format won't be understood by GNU date
# reformat, then return date as seconds
reformat_date(){
    year=$(cut -d/ -f3<<<$(cut -d : -f1 <<<"$1"))
    month=$(cut -d/ -f2<<<$(cut -d : -f1 <<<"$1"))
    day=$(cut -d/ -f1<<<$(cut -d : -f1 <<<"$1"))

    hour=$(cut -d : -f2 <<<"$1")
    min=$(cut -d : -f3 <<<"$1")
    sec=$(cut -d : -f4 <<<"$1")

    date +%s -d "$(printf '%s-%s-%s %s:%s:%s' "$year" "$month" "$day" "$hour" "$min" "$sec")"
}

from=$(reformat_date "$1")

flag=
while IFS= read -r d ; do
    d_s=$(reformat_date "$d")
    if [ -z $flag ] && [ $(expr "$d_s" - "$from") -gt 0 ] ; then
            flag=1
    fi

    if [ ! -z $flag ] ; then
            printf '%s\n' "$d"
    fi
done < "$2"

另存为脚本,将输入日期作为第一个参数传递,将文件名作为第二个参数处理。输出第一行之后出现的文件行晚于输入日期和时间(包括第一行)。

所以

./dates_from.sh '2/04/2002:11:30:41' dates.list > results.list

您发布的伪代码似乎没有执行上述句子所描述的内容,因此我忽略了它。