0

bash、sed、awk の専門家の 1 人が私を助けてくれることを願っています。私はこの文字列を持っています:

 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     

「%~%」で区切られたフィールドです。最初の 2 つのフィールドは無視できます。残りのフィールドには、日中の範囲があります。これにより、形式が明確になります。

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文が必要です。範囲内にある場合は 1 つのスクリプトを実行し、そうでない場合は別のスクリプトを実行する必要があります。bash、awk、および/またはsedを使用してそれを行うにはどうすればよいですか?

ご協力いただきありがとうございます。

私はこの道を進み始めました:

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

3 に答える 3

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
于 2012-09-19T22:37:06.860 に答える
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

あなたの問題を正しく理解できたと思います。ご不明な点がございましたら、お気軽にお問い合わせください。

于 2012-09-19T22:46:38.150 に答える
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"
            }
        }
    }
}
于 2012-09-20T00:34:16.877 に答える