この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)):00
counter+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:00
07: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