使用awk解析年龄字符串

使用awk解析年龄字符串

我需要解析 Kubernetes/OpenShift 监控脚本的 Pod 的年龄。

我需要比较 pod 的使用期限,并通知 pod 长时间处于某种状态。例如,Pod 的寿命显示为 1d - 一天、1h - 一小时、10m - 十分钟或 5s - 五秒。实际上,它可能类似于 1d5m24s。

我的问题是如何最好地解析和比较豆荚的年龄?我尝试过使用 awk 内部的日期实用程序,但它实际上并不解析这样的字符串。 awk 有什么好的方法可以做到这一点吗?

我正在解析的一些示例输出:

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

答案1

目前尚不清楚您实际想要执行的计算结果是什么,因此这里有一个 GNU awk (对于第四个参数 to split())脚本,该脚本将仅打印每个时间戳的秒数,假设我们不必考虑 DST 和/或闰秒:

$ 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,该持续时间格式实际上是由 ast-open 的时间解析例程识别的,包括%Torksh93printf内置函数(以及标准 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这也是其's指令使用的格式,%Q尽管您获得的精度有点任意(只有两个组成部分):

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

相关内容