awkを使用してbashスクリプトで変数を使用する

awkを使用してbashスクリプトで変数を使用する

このawkコマンドを動的に呼び出すスクリプトを作成したいと思います。

awk '/2019.07.16 09:00/, /2019.07.16 10:00:/' mylog.log | awk '$3 == "-" && $4 != "-" {print $4}' | sort | uniq | wc -l

通常、コマンドを呼び出すと成功しますが、コマンドを数回実行して時間範囲を変更しようとするため、時間を設定するのに問題があります。試した方法は次のとおりです。

for counter in {7..7}
    do
        echo "Counter "$counter
        echo /2019.07.16 0"$counter":00/, /2019.07.16 0"$((counter+1))":00:/

        # The commented code shows unsuccessful attempts
        #awk '/2019.07.16 0"$counter":00/, /2019.07.16 "$((counter+1))":00:/' mylog.log | awk '$3 == "-" && $4 != "-" {print $4}' | sort | uniq | wc -l

        # The commented code shows unsuccessful attempts
        #startvar=0"$counter":00/,
        #echo $startvar
        #awk -v start="$startvar" '/2019.07.16 start /2019.07.16 08:00:/' mylog.log | wc -l                 
    done

どのようなヒントがありますか?よろしくお願いします。

ベストアンサー1

一重引用符の代わりに二重引用符を使用すると、引用符間の変数置換が機能します。このアプローチでは、スクリプトのすべてと文字を引用符$で囲む必要があります。"awk\$\"

awk "/2019.07.16 0$counter:00/, /2019.07.16 0$((counter+1)):00:/" mylog.log | ...

とのソリューションのみ0$counter:00有効です。0$((counter+1)):00counter+1 < 10

2 桁の時間値もフィルタリングするには、時間文字列に printf 形式を使用できます。

start=$(printf "%2.2d" "$counter")
stop=$(printf "%2.2d" "$((counter+1))")

awk "/2019.07.16 $start:00:/, /2019.07.16 $stop:00:/" mylog.log | ...

実際の入力データの各行に日付と時刻が含まれていて、次の時間の00分を必要としない場合は、パターンを単純化できます。

awk "/2019.07.16 $start:/" mylog.log | ...

start=07たとえば、からのすべての行を印刷する必要があります。07:00:0007:59:59

awkこの単純化により、2つのスクリプトを1つにまとめることができます。

awk "/2019.07.16 $start:/ && \$3 == \"-\" && \$4 != \"-\" {print \$4}" mylog.log | sort -u | wc -l

注:sort -uと同じ出力を提供しますsort | uniq

より良い解決策を得るには、入力データの正確な形式を知る必要があります。

日付が列1にあり、時間が列2にあると仮定すると、awkスクリプトコードでシェル変数拡張なしでデータを変数に渡すことができますawk。このソリューションを使用すると、一重引用符を使用でき、コード挿入の脆弱性だけでなく、スクリプトの引用や$参照も防止できます。"

timepattern=$(printf "^%2.2d:" "$counter")
date="2019.07.16"

awk -v date="$date" -v timepattern="$timepattern" '$1 == date && $2 ~ timepattern && $3 == "-" && $4 != "-" {print $4}' mylog.log | sort -u | wc -l

おすすめ記事