2009-10-27 54 views
9

我试图创建一个脚本,它将通过文件以下列格式写入文件:yyyymmdd.hh.filename。在两个给定的日期之间的bash循环

该脚本调用:

./loopscript.sh 20091026.00 23 
./loopscript.sh 20091026.11 15 
./loopscript.sh 20091026.09 20091027.17 

需要的是对脚本来检查这两个指定的日期/小时之间的每个小时。

例如

cat 20091026.00.filename |more 
cat 20091026.01.filename |more 
... 
cat 20091026.23.filename |more 
cat 20091027.01.filename |more 
cat 20091027.02.filename |more 
... 

等等。

任何想法该怎么办?我对标准的0 - x循环没有任何困难。或简单的循环。只是不知道如何去上述。

+0

无用的'cat':只使用'更多文件名' – 2009-10-27 09:43:08

回答

5

要处理两个给定日期/小时之间的每个文件,可以使用以下命令:

#!/usr/bin/bash 
#set -x 

usage() { 
    echo 'Usage: loopscript.sh <from> <to>' 
    echo '  <from> MUST be yyyymmdd.hh or empty, meaning 00000000.00' 
    echo '  <to> can be shorter and is affected by <from>' 
    echo '   e.g., 20091026.00  27.01 becomes' 
    echo '    20091026.00 20091027.01' 
    echo '   If empty, it is set to 99999999.99' 
    echo 'Arguments were:' 
    echo " '${from}'" 
    echo " '${to}'" 
} 

# Check parameters. 

from="00000000.00" 
to="99999999.99" 
if [[ ! -z "$1" ]] ; then 
    from=$1 
fi 
if [[ ! -z "$2" ]] ; then 
    to=$2 
fi 
## Insert this to default to rest-of-day when first argument 
## but no second argument. Basically just sets second 
## argument to 23 so it will be transformed to end-of-day. 
#if [[ ! -z "$1"]] ; then 
# if [[ -z "$2"]] ; then 
#  to=23 
# fi 
#fi 

if [[ ${#from} -ne 11 || ${#to} -gt 11 ]] ; then 
    usage 
    exit 1 
fi 

# Sneaky code to modify a short "to" based on the start of "from". 
# ${#from} is the length of ${from}. 
# $((${#from}-${#to})) is the length difference between ${from} and ${to} 
# ${from:0:$((${#from}-${#to}))} is the start of ${from} long enough 
# to make ${to} the same length. 
# ${from:0:$((${#from}-${#to}))}${to} is that with ${to} appended. 
# Voila! Easy, no? 

if [[ ${#to} -lt ${#from} ]] ; then 
    to=${from:0:$((${#from}-${#to}))}${to} 
fi 

# Process all files, checking that they're inside the range. 

echo "From ${from} to ${to}" 
for file in [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].[0-9][0-9].* ; do 
    if [[ ! (${file:0:11} < ${from} || ${file:0:11} > ${to}) ]] ; then 
     echo " ${file}" 
    fi 
done 

当您创建的文件20091026.00.${RANDOM}通过20091028.23.${RANDOM}包括,这是一对样品运行:

pax> ./loopscript.sh 20091026.07 9 
From 20091026.07 to 20091026.09 
    20091026.07.21772 
    20091026.08.31390 
    20091026.09.9214 
pax> ./loopscript.sh 20091027.21 28.02 
From 20091027.21 to 20091028.02 
    20091027.21.22582 
    20091027.22.30063 
    20091027.23.29437 
    20091028.00.14744 
    20091028.01.6827 
    20091028.02.10366 
pax> ./loopscript.sh 00000000.00 99999999.99 # or just leave off the parameters. 
    20091026.00.25772 
    20091026.01.25964 
    20091026.02.21132 
    20091026.03.3116 
    20091026.04.6271 
    20091026.05.14870 
    20091026.06.28826 
    : : : 
    20091028.17.20089 
    20091028.18.13816 
    20091028.19.7650 
    20091028.20.20927 
    20091028.21.13248 
    20091028.22.9125 
    20091028.23.7870 

正如你所看到的,第一个参数必须是正确的格式yyyymmdd.hh。第二个参数可以更短,因为它继承了第一个参数的开始,使其成为正确的长度。

这只会尝试处理存在(从ls)和正确格式的文件,而不是每个日期/小时范围内的文件。如果你有稀疏文件(包括范围的开始和结尾),这将更有效率,因为它不需要检查文件是否存在。

顺便说一句,这是创建的测试文件的命令,如果你有兴趣:

pax> for dt in 20091026 20091027 20091028 ; do 
     for tm in 00 01 02 ... you get the idea ... 21 22 23 ; do 
      touch $dt.$tm.$RANDOM 
     done 
    done 

请不要输入,在逐字,然后抱怨说,它创建的文件,如:

20091026.you.12345 
20091028.idea.77 

我只修剪了这条线,所以它适合代码宽度。 :-)

+0

哇,我被这个答案吹走了。我会回到你们家。 – Chasester 2009-10-27 08:25:00

+0

如果有人输入./loopscript.sh 20091026.07没有值。它会从20091026.07运行到20091023.07有没有办法将它默认为.23?我有这个代码的最上面部分 - 将当前日期设置为=“$(date +%Y)$(date +%m)$(date +%d)”的st/end时间 “ .00“ to =”$(date +%Y)$(date +%m)$(date +%d)“。23” if [[! -z“$ 2”]];然后 from = $ 2 fi if [[! -z“$ 3”]];那么 到= $ 3 fi if [[$ {#from} -ne 11 || $ {#to} -gt 11]];然后 用法 出口1 fi if [[$ {#to} -lt $ {#from}]];然后 to = $ {from:0:$(($ {#from} - $ {#to}))} {{to} fi – Chasester 2009-10-27 10:14:02

+0

而不是前两个测试,只需对位置参数进行第三个测试直接:'$ {#1}'后跟赋值如'from = {{1:-00000000.00}''。创建测试文件内循环:'for tm in 0 {0..24}; do touch $ dt。$ {tm:-2}。$ RANDOM; done'或没有内部循环:'touch $ dt.0 {0..9}。$ RANDOM;触摸$ dt。{10..19}。$ RANDOM;触摸$ dt。{20..23}。$ RANDOM' – 2009-10-27 10:31:20

1

一种可能的解决方案:将日期转换为标准的Unix表示形式,即“从历元开始经过的秒数”和循环,每次迭代将此数字增加3600(一小时内的秒数)。例如:

#!/bin/bash 

# Parse your input to date and hour first, so you get: 
date_from=20090911 
hour_from=10 
date_to=20091026 
hour_to=01 

i=`date --date="$date_from $hour_from:00:00" +%s` 
j=`date --date="$date_to $hour_to:00:00" +%s` 

while [[ $i < $j ]]; do 
    date -d "1970-01-01 $i sec" "+%Y%m%d.%H" 
    i=$[ $i + 3600 ] 
done 
+0

建议每小时有3600秒 - 并按要求增加小时数。 – 2009-10-27 06:42:47

+0

由于时区的限制,此代码会产生几个小时的差异。 – kachar 2012-07-23 11:06:52

23

如何:

#!/bin/bash 

date1=$1 
date2=$2 

#verify dates 
if ! date -d "$date1" 2>&1 > /dev/null ; 
    then echo "first date is invalid" ; exit 1 
fi 
if ! date -d "$date2" 2>&1 > /dev/null ; 
    then echo "second date is invalid" ; exit 1 
fi 

#set current and end date 
current=$(date -d "$date1") 
end=$(date -d "$date2 +1 hours") 

#loop over all dates 
while [ "$end" != "$current" ] 
do 
    file=$(date -d "$current" +%Y%m%d.%H) 
    cat $file."filename" | more 
    current=$(date -d "$current +1 hours") 
done 
+0

这是合理的日期,但不处理小时。其实,对日期也有一定的怀疑 - 如果你给它的参数20091027和20091028,你会从20091027.00到20091028.00获得 - 我预计它会停在1027.23或1028.23。 – paxdiablo 2009-10-27 07:26:58

+0

如果您以“20091027 00”“20091028 03”来称呼它,它会处理几小时,忘记提及这一点。 – Puppe 2009-10-27 07:36:09

+0

艾啊,那好点。据推测,这是做日常工作的日期。不错。 – paxdiablo 2009-10-27 07:41:29

相关问题