开发者

how to manage dates in shell

I have a file containing 14000 dates . I wrote a script to find the last 5 days ,

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开发者_StackOverflow社区/2002:11:52:25

suppose this is the file , now I have date 02/04/2002:11:30:41 as an out put . I want to put the dates from 02/04/2002 till the end of the file in another file .

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)

this code suppose to do so but it has problem ! why?

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


Assuming that the file is sorted by date-time:

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

Prints from the first line starting with 02/04/2002 to the end of the file.


I haven't used it myself, but the gawk command (GNU's AWK) has the ability to manipulate date/time strings. And, gawk is the Linux version of the awk command.

You can also rewrite your whole program as a single awk script. That might make things a lot easier. Remember awk is a full blown programming language that simply assumes a read loop on the file and processes each line of a file.


programmatically, you can find the 5th last day like this:

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

Then, you can print all days greater than or equal to this day:

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


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


I wrote a whole set of tools (dateutils) to tackle these kinds of problems. In your case it's simply:

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

where the -i option specifies the input format and >=02/04/2002:11:30:41 is your cut-off date (>= means dates younger than the one specified of course).


Is this what you want?

#!/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"

Save as a script, pass your input date as the first argument and a filename to process as the second argument. Outputs lines from the file which appear after the first line to be later than the input date and time (including the first line).

So

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

The pseudo-code you posted doesn't seem to do what the preceding sentence described, so I ignored it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜