使用bash解析日期时间范围

时间:2012-09-19 21:35:18

标签: bash date sed awk grep

我希望你们中的一个人,bash,awk专家可以帮助我。我有这个字符串:

 00:00:00:00:00:00%~%System1%~%s0:00-21:40%~%m3:10-17:10%~%t11:20-20:30%~%w05:10-9:30%~%t00:00-21:30%~%f12:00-0:00%~%s6:00-18:00     

由“%〜%”分隔的字段。前两个字段可以忽略。其余字段具有日期时间范围。这应该澄清格式:

00:00:00:00:00:00 <--Mac
System1           <--Name
s00:00-21:40      <--Sunday 12 AM through 9:40 PM  
m03:10-17:10      <--Monday 3:10 AM through 5:10 PM
t11:20-20:30      <--Tuesday 11:20 AM through 8:30 PM
w05:10-9:30       <--Wednesday 5:10 AM through 9:30 AM
t00:00-21:30      <--Thursday 12 AM through 9:30 PM
f12:00-0:00       <--Friday 12 PM through 12:00 AM
s06:00-18:00      <--Saturday 6 AM through 6:00 PM

现在的诀窍......我需要确定当前系统日期时间是否在范围内。 : - (

所以,如果日期返回:

 Wed Sep 19 14:26:05 UTC 2012

然后它不在星期三指定的范围内。我基本上需要一个if语句。如果它在范围内,我需要执行一个脚本,如果不是,则需要执行不同的脚本。我怎么能用bash,awk和/或sed做到这一点?

感谢您提供的任何帮助!

我开始走这条路:

arr=$(echo $line | tr "%~% " "\n")
for x in $arr
do
    #Now what?  Some kind of switch/case?
done

3 个答案:

答案 0 :(得分:1)

我相信以下脚本可以满足您的需求:

#!/bin/bash

# Function which returns true (0) on a time being in a range, false (1) otherwise
# call as: time_between $time $range
# where $range is of the format 'START-END'
time_between() {
    current_time=$1
    range=$2

    start_time=$(echo $range | cut -d'-' -f1);
    end_time=$(echo $range | cut -d'-' -f2);

    # Correct if ends at midnight
    if [[ $end_time -eq 0 ]]; then
        let end_time=2400
    fi

    # Test is time is within the window
    if [[ $current_time -ge $start_time && $current_time -le $end_time ]]
    then
         return 0;
    fi

    # Else the time is outside the window
    return 1;
}

# Set the line variable - you may want this to come from somewhere else in the end  
line="00:00:00:00:00:00%~%System1%~%s0:00-21:40%~%m3:10-17:10%~%t11:20-20:30%~%w05:10-9:30%~%t00:00-21:30%~%f12:00-0:00%~%s6:00-18:00"

i=0

# Extract the day and time (hours and minutes) from the `date` command
DATE=$(date)
day=$(echo $DATE | cut -d' ' -f1)

time=$(echo $DATE | cut -d' ' -f4 | cut -d: -f1-2 | tr -d ':')

# Marker for which token in the line to start the days from: token 3 is monday
dayno=2

# Set the dayno so we're pointing at the current day
case $day in
Mon)
    let dayno+=1
;;
Tue)
    let dayno+=2
;;
Wed)
    let dayno+=3
;;
Thu)
    let dayno+=4
;;
Fri)
    let dayno+=5
;;
Sat)
    let dayno+=6
;;
Sun)
    let dayno+=7
;;
esac

arr=$(echo $line | tr '%~%' '\n' | tr -d '[a-z]:')

for x in $arr
do
    let i+=1;
    #Now what?  Some kind of switch/case?
    if [[ $i -eq $dayno ]]; then
        if time_between $time $x; then
            echo "Were within the window!"
        else
            echo "We missed the window!"
        fi
    fi
done

答案 1 :(得分:1)

这是使用awk的解决方案。我认为getline / coprocess特性是特定于GNU Awk的,所以如果你发现这个解决方案可以接受,请确保使用它。

<强> script.awk

BEGIN {
    RS = "%~%"
    "date +%w"   | getline dow
    "date +%H%M" | getline now
}

NR == 1      { mac = $0; next }
NR == 2      { sys = $0; next }

NR == 3+dow  {
    str = $0
    gsub(/[smtwf:]/, "", str)
    split(str, period, "-")
    next
 }

END {
    print "MAC:",  mac;
    print "System:", sys;
    print "Now:", now;
    print "Period:", period[1], period[2] ;

    if ((now >= period[1]) && (now <= period[2])) {
         # change this ...
         cmd = sprintf("echo matched - mac: %s system: %s", mac, sys)
         system(cmd)
    } else {
         # ... and this
         system("echo not matched")
    }
}

<强>用法

$ date
Thu Sep 20 01:44:12 EEST 2012

$ echo "$data" | awk -f script.awk 
MAC: 00:00:00:00:00:00
System: System1
Now: 0145
Period: 0000 2130
matched - mac: 00:00:00:00:00:00 system: System1

我希望我能正确理解你的问题。随意请求澄清。

答案 2 :(得分:1)

使用GNU awk的一种方式:

echo "$string" | awk -f script.awk

script.awk的内容:

BEGIN {
    FS="%~%"
    day = strftime("%w") + 3
    time = strftime("%H%M")
}

{
    for (i=1; i<=NF; i++) {
        if (i == day) {
            gsub(/[a-z:]/,"")
            split($i, period, "-")
            if ((time >= period[1]) && (time <= period[2])) {
                print "yes, we're within today's range"
            }
            else {
                print "no, we're not within today's range"
            }
        }
    }
}