awkを使用した年齢文字列の解析

awkを使用した年齢文字列の解析

Kubernetes / OpenShiftモニタリングスクリプトのためにPodの寿命を解析する必要があります。

Podの寿命を比較して、Podが長い間特定の状態にあることを知らせる必要があります。たとえば、Podの寿命は1d - 1日、1h - 1時間、10m - 10分、または5s - 5秒で表示されます。実際にはおそらく1d5m24sほどでしょう。

私の質問は、フォードの寿命を解析して比較する最良の方法は何ですか?私はawk内で日付ユーティリティを試しましたが、実際にそのような文字列を解析しません。 awkでこれを行うための良い方法はありますか?

私が解析する内容のいくつかの出力例は次のとおりです。

NAME                                                    READY     STATUS      RESTARTS   AGE
testpod-4e8e492d                                        0/1       Error       0          30h
another-testpod-d1ed34d7                                0/1       Error       0          31h

答え1

実際に実行したい計算が何であるかは明確ではないので、ここにsplit()DSTおよび/またはホッピングを考慮する必要がないという仮定の下で、各タイムスタンプの秒数だけを印刷するGNU awk(の4番目の引数に対する)スクリプトがあります。秒:

$ cat tst.awk
BEGIN {
    OFS = "\t"
    mult["s"] = m = 1
    mult["m"] = m *= 60
    mult["h"] = m *= 60
    mult["d"] = m *= 24
}
NR == 1 {
    secs = "SECS"
}
NR > 1 {
    secs = 0
    n = split($NF,number,/[[:alpha:]]/,denomination)
    for ( i=1; i < n; i++ ) {
        secs += number[i] * mult[denomination[i]]
    }
}
{
    print $0, secs
}

$ awk -f tst.awk file
NAME                                                    READY     STATUS      RESTARTS   AGE    SECS
testpod-4e8e492d                                        0/1       Error       0          30h    108000
another-testpod-d1ed34d7                                0/1       Error       0          31h    111600
another-testpod-d1ed34d7                                0/1       Error       0          1d5m24s    86724

上記のコードはこの入力ファイルで実行されます。

$ cat file
NAME                                                    READY     STATUS      RESTARTS   AGE
testpod-4e8e492d                                        0/1       Error       0          30h
another-testpod-d1ed34d7                                0/1       Error       0          31h
another-testpod-d1ed34d7                                0/1       Error       0          1d5m24s

GNU awkがない場合は、どんなawkでも使用できます。

$ cat tst.awk
BEGIN {
    OFS = "\t"
    mult["s"] = m = 1
    mult["m"] = m *= 60
    mult["h"] = m *= 60
    mult["d"] = m *= 24
}
NR == 1 {
    secs = "SECS"
}
NR>1 {
    secs = 0
    time = $NF
    while ( match(time,/[^0-9]/) ) {
        secs += substr(time,1,RSTART-1) * mult[substr(time,RSTART,1)]
        time = substr(time,RSTART+1)
    }
}
{
    print $0, secs
}

答え2

これは一般的なタイムスタンプ形式ではありません。。手動で解析する必要があります。 (相対的に)単純な(しかし反復的な)正規表現を使うことは非常に簡単です。

GNU awkを使う:

for ts in 2d34h4m56s 2d 34h 4m 56s 34h4m; do
  echo "$ts" | gawk '
    match($1, "(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?", m) {
      printf "%d days, %d hours, %d minutes, %d seconds\n", m[2], m[4], m[6], m[8]
    }
  '
done
2 days, 34 hours, 4 minutes, 56 seconds
2 days, 0 hours, 0 minutes, 0 seconds
0 days, 34 hours, 0 minutes, 0 seconds
0 days, 0 hours, 4 minutes, 0 seconds
0 days, 0 hours, 0 minutes, 56 seconds
0 days, 34 hours, 4 minutes, 0 seconds

答え3

FWIW、その期間形式は、%Tまたはksh93printf組み込み関数(および標準ISO8601期間これに似ています)。

$ ksh -c 'printf "%(%s)T\n" "#0 1d5m24s"'
86724

(ここでこの期間をエポック秒0()に追加して#0秒数を取得します。)

したがって、ksh93次のことができます。

#! /bin/ksh93 -
(( threshold = 12 * 60 * 60 )) # 12 hours for instance
{
  read -rA headers
  while read -r "${headers[@]}" rest; do
    seconds=${ printf '%(%s)T' "#0 $AGE"; }
    if (( seconds > threshold )); then
      print -r -- "$NAME is over 12 hours old"
    fi
  done
} < that-file

printf%Q取得する精度はややランダムですが(2つのコンポーネントのみ)、これは「指示文で使用される形式」です。

$ ksh -c 'printf "%Q\n" 123456'
1d10h

関連情報