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.
精彩评论