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(의 네 번째 인수에 대한) 스크립트가 있습니다. 초:

$ 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얻는 정밀도는 다소 임의적이지만(단 두 가지 구성 요소만) 이는 '지시문에서 사용되는 형식이기도 합니다 .

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

관련 정보