unix 遍历While read分隔shell脚本中的字符串

t9eec4r0  于 2022-11-04  发布在  Unix
关注(0)|答案(1)|浏览(203)

我有一个名为test.json的json文件,我想解析id、name和not_after的值,然后放入条件以验证not_after不应超过60天。
vi测试. json

{
  "id" : 10001,
  "name" : "Test Client Name",
  "type" : "PKCS12",
  "provider" : "SunJSSE",
  "password" : "1111111",
  "url" : "data:application/xxxx-xxx,1234567890987",
  "entry" : [ {
    "alias" : "example.com,
    "type" : "PrivateKeyEntry",
    "algorithm" : "EC",
    "subject" : "C=CA, ST=ON, L=Toronto, O=Techonology, OU=example, CN=example.com",
    "issuer" : "C=US, O=example Lab, CN=ExampleCA",
    "not_before" : "Fri, 21 Aug 2020 19:44:26 GMT",
    "not_after" : "Sun, 21 Aug 2022 19:44:26 GMT",
    "tn_auth_list" : [ {
      "spc" : "AA001"
    } ]
  } ],
  "created_date" : "Thu, 20 Aug 2020 04:38:16 GMT"
}{
  "id" : 10002,
  "name" : "client-02",
  "type" : "PKCS12",
  "provider" : "SunJSSE",
  "password" : "1111111",
  "url" : "data:application/xxxx-xxx,1234567890987",
  "customer_id" : 12002,
  "entry" : [ {
    "alias" : "example.com",
    "type" : "PrivateKeyEntry",
    "algorithm" : "EC",
    "subject" : "C=US, ST=CA, L=San Ramon, O=Five9, OU=example, CN=example.com",
    "issuer" : "C=US, O=example Lab, CN=ExampleCA",
    "not_before" : "Tue, 2 Jun 2020 12:15:36 GMT",
    "not_after" : "Thu, 2 Jun 2022 12:15:36 GMT",
    "tn_auth_list" : [ {
      "spc" : "ZZ001"
    } ]
  } ],
  "created_date" : "Mon, 14 Dec 2020 21:42:35 GMT"
}

jq的输出在读取时不能被视为一个字符串,所以条件不能正常工作,如果我只给予 .entry[].not_after,我可以得到 not_after 的输出。需要一些帮助,while read 不应该破坏名称字符串,它应该将名称视为单个字符串。

cat test.json | jq -r '.name, .entry[].not_after' | while read name expirydate; do
    echo certname=$name
    echo expiryday=$expirydate
    not_after="${expirydate}"
    echo expirydate=$not_after

    condition=$(( $(date +%s) + $((60*24*60*60)) ))
    echo condition=$condition

    not_after_in_seconds=$(date -d "$not_after" +%s)
    # echo not_after_in_seconds: $not_after_in_seconds
    # echo not_after_in_date: $(date -d @$not_after_in_seconds)

    if [ $condition -ge $not_after_in_seconds ]
    then
      echo Certificate name : $certname will be expire in 60 days, Expiration Date = $not_after
    else
      echo No issues for 60 days
     fi
done

输出:

certname=Test
expiryday=Client Name
expirydate=Client Name
condition=1661241563
date: invalid date 'Client Name'
./dummy.sh: line 15: [: 1661241563: unary operator expected
No issues for 60 days
certname=Sun,
expiryday=21 Aug 2022 19:44:26 GMT
expirydate=21 Aug 2022 19:44:26 GMT
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date = 21 Aug 2022 19:44:26 GMT
certname=client-02
expiryday=
expirydate=
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date =
certname=Thu,
expiryday=2 Jun 2022 12:15:36 GMT
expirydate=2 Jun 2022 12:15:36 GMT
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date = 2 Jun 2022 12:15:36 GMT

预期输出:

Certificate name : Test Client Name will be expire in 60 days, Expiration Date = 21 Aug 2022 19:44:26 GMT
Certificate name : client-02 will be expire in 60 days, Expiration Date = 2 Jun 2022 12:15:36 GMT
8yparm6h

8yparm6h1#

我们可以使用| @sh来引用JSON数组,以便shell进行求值:

jq -r '[.name, .entry[].not_after ] | @sh' test.json

提供:

'Test Client Name' 'Sun, 21 Aug 2022 19:44:26 GMT'
'client-02' 'Thu, 2 Jun 2022 12:15:36 GMT'

现在我们有了一个包含四个独立单词的列表,我们可以使用eval将其存储在一个bash数组中。
示例脚本:


# !/bin/bash

eval "a=($(jq -r '[.name, .entry[].not_after ] | @sh'))"

for ((i=0; i<${#a[@]}; i+=2)); do
    name=${a[i]} expiry=${a[i+1]}

    expiry_epoch=$(date -d "$expiry" +%s)
    now_epoch=$(date +%s)

    days_left=$(( (expiry_epoch - now_epoch) / 86400 ))

    if ((days_left == 0)); then
        echo "$name: warning: expires today"
    elif ((days_left < 0)); then
        echo "$name: EXPIRED $((days_left*-1)) days ago"
    elif ((days_left < 60)); then
        echo "$name: warning: expires in $days_left" days
    else
        echo "$name: $days_left days left"
    fi
done

使用方式:expiry-script < test.json
正确计算剩余天数并不总是那么简单。此脚本会截断当前日期(即4.9天变为4天)。这可能是所需的,但如果时区采用夏令时,则每年也会错误一小时。DST会导致一天为23小时,这意味着一天在不应该截断的时候被截断。
另一个没有这个问题的方法是向上或向下舍入到最近的一天:

printf -v days_left %.0f \
    "$(echo "scale=1; ($expiry_epoch - $now_epoch)/86400" | bc)"

这是一个不同的方法。舍入确实避免了DST问题。

相关问题