

このようなリストがあります。このリストは標準入力から入力されます。

[code]

    -06
    26
    56
    -07
    26
    54
    -08
    27
    55
    -10
    01
    -11
    01
    -12
    01
    -13
    01
    52
    -14
    52
    
[/code]

次にdateコマンドで時刻を取得し変数に格納します。

そして最初にリストにある時間で最も近い時間を捜索します。  
次にそこから３つの時刻を取得して返すようにしたいです。

たとえば８時30分であれば配列で「0855 1001 1101」を返します。  
また16時であればそれ以上直近のものがないのでその場合は最初に戻り翌日の6時のものから捜索し数字冒頭に99を付加した「990626 990656
990726」を返したいです。これは他にもデーターを処理して近い順にソートする際に当日のものが別のデーターに含まれていた場合に翌日のものが当日のものより早くなってしまうことを防ぐためにつけるものです。

お手数おかけしますがよろしくおねがいします


CC BY-SA 4.0
2019-04-20T14:54:34.400
54344
2019-06-17T11:29:21.040
33004
question
linux bash
シェルスクリプトでリストから近い時間のものを抽出したい。


とりあえず sed と awk と/bin/sh で書いてみました。  
ただしある程度複雑なテキスト処理になったらシェルスクリプトではなくもう少し高機能なスクリプト言語(perl, python, ruby
など)で書いた方が性能も保守性もよくなるかと思います。

[code]

    #! /bin/sh
    
    # 1. create today table
    TMP_FILE=`mktemp`
    awk -F'-' 'BEGIN{OFS=""} {if ($2 != "" ) hour=$2; else print hour, $1}' - > ${TMP_FILE}
    
    # 2. create today and tommorow table
    TMP_FILE2=`mktemp`
    cat ${TMP_FILE} >> ${TMP_FILE2}
    sed -e s/^/99/g ${TMP_FILE} >> ${TMP_FILE2}
    
    # 3. get current time
    NOW=`date +%H%M`
    #NOW=0830 # for test
    #NOW=1600 # for test
    
    # 4. search 3 items after NOW
    awk "{ if (\$0 >= \"$NOW\") print \$0 }" < ${TMP_FILE2} | head -3
    
    # 5. clean up tmp files
    if [ -f ${TMP_FILE2} ]; then
        rm ${TMP_FILE2}
    fi
    
    if [ -f ${TMP_FILE} ]; then
        rm ${TMP_FILE}
    fi
    
[/code]


CC BY-SA 4.0
2019-04-22T08:49:50.647
54388
2019-04-22T08:49:50.647
27410
54344
answer


AWK でよろしければこんな感じでしょうか。

[code]

    cat list.txt | awk '
    {
        # read input file and generate list of time
        if (gsub("^-", "")) {
            hh = $0
        } else {
            list[++i] = hh $0;
        }
    }
    END {
        # get current time
        "date +%H%M" | getline
        date = $0
    
        # add tomorrow's list
        for (j = 1; j <= i; j++) {
            list[j + i] = "99" list[j]
        }
    
        # search in the list
        for (j = 1; j <= 2 * i; j++) {
            if (date <= list[j]) {
                # found and print 3 items
                for (k = j;  k < j + 3; k++) {
                    print list[k]
                }
                exit
            }
        }
    }'
    
[/code]


CC BY-SA 4.0
2019-06-17T02:39:02.090
55866
2019-06-17T02:39:02.090
25106
54344
answer


sed でも一行で書けます。

時分の文字列比較が多少厄介ですが、「以上」を求めるには「未満」を全て削除すればよいと発想転換できれば難しくありません。  
例えば、`830` 以上を求めるには `[^8-9]..` と `8[^3-9].` と `83[^0-9]` を削除すれば残った数が答えになります。

[code]

    HHMM=`date +%H%M`; H0=${HHMM:0:1}; H1=${HHMM:1:1}; M0=${HHMM:2:1}; M1=${HHMM:3:1}
    
    sed '-e:a;N;${;:b;s/-\([0-2][0-9]\)\(\n[^-]*\n\)\([0-5][0-9]\n\)/-\1\2\1\3/g;tb;s/-\([0-2][0-9]\)\n\([0-5][0-9]\)/\1\2/g;h;s/\(^\|\n\)/\199/g;x;s/$/\n/;s/[^'$H0'-9]...\n//g;s/'$H0'[^'$H1'-9]..\n//g;s/'$H0$H1'[^'$M0'-9].\n//g;s/'$H0$H1$M0'[^'$M1'-9]\n//g;s/\n$//;G;s/^\n//;s/\n/ /;s/\n/ /;s/\n.*//;};ba'
    
[/code]


CC BY-SA 4.0
2019-06-17T11:29:21.040
55882
2019-06-17T11:29:21.040
8431
54344
answer