排序bash脚本错误



我正在尝试按日期对证书进行排序,只将最新的证书保留在一个单独的文件中。

以下是一个示例主机的示例pki_certs.res输入文件,其中包含我需要排序的过去证书列表:

下面是排序并弹出最后一个的脚本:

cat "${_file}" | sort -k10,10 | sed -e 's/Not After : //' -e 's/GMT/GMT;/' | grep "${_domain}" | 
while read line; do
_first=`echo $line | cut -d';' -f1`
_second=`echo $line | cut -d';' -f2-`
_date=`date -d "${_first}" +%Y%m%d%H%M`
echo "$_date $_second"
done |sort -k 3,3 -k 1,1r | awk "{if (i[$3] < $1) i[$3]=$1} END{for(x in i){ print x" "i[x] }}" | 
sed -e 's/CN=//g' | sort -k 2,2 > pki_certs.final.sorted

问题是排序在pki_certs.final.sorted文件中留下了最近的前一个。

预期输出:

Apr 7 20:09:26 2023

但我得到的不是这样的输出:

Apr 12 18:12:02 2022

关于我错过了什么,有什么想法吗

使用任何版本的强制性Unix工具awk、Sort、cut和head应用DSU(Decorate/Sort/Uncorate(习惯用法以获得整行输出:

$ awk '{printf "%04d%02d%02d%st%sn", $7, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$4)+2)/3, $5, $6, $0}' file |
sort -r | head -1 | cut -f2-
pki_certs.res:Not After : Apr 7 20:09:26 2023 GMT DNS:MDVARTREPO01.cpp.nonlive

或者只是日期:

$ awk '{printf "%04d%02d%02d%st%sn", $7, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$4)+2)/3, $5, $6, $4" "$5" "$6" "$7}' file |
sort -r | head -1 | cut -f2-
Apr 7 20:09:26 2023

第一个awk在每行的前面添加一个日期+时间的可排序版本,然后根据时间戳对其进行排序,然后剪切删除awk添加的字符串。看到每一步的中间输出可以看出它是如何工作的:

$ awk '{printf "%04d%02d%02d%st%sn", $7, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$4)+2)/3, $5, $6, $4" "$5" "$6" "$7}' file
2023040720:09:26        Apr 7 20:09:26 2023
2020050712:05:44        May 7 12:05:44 2020
2021040817:06:54        Apr 8 17:06:54 2021
2020050711:58:19        May 7 11:58:19 2020
2021040917:42:27        Apr 9 17:42:27 2021
2021041709:09:35        Apr 17 09:09:35 2021
2021040917:02:43        Apr 9 17:02:43 2021
2022041218:12:02        Apr 12 18:12:02 2022

$ awk '{printf "%04d%02d%02d%st%sn", $7, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$4)+2)/3, $5, $6, $4" "$5" "$6" "$7}' file | sort -r
2023040720:09:26        Apr 7 20:09:26 2023
2022041218:12:02        Apr 12 18:12:02 2022
2021041709:09:35        Apr 17 09:09:35 2021
2021040917:42:27        Apr 9 17:42:27 2021
2021040917:02:43        Apr 9 17:02:43 2021
2021040817:06:54        Apr 8 17:06:54 2021
2020050712:05:44        May 7 12:05:44 2020
2020050711:58:19        May 7 11:58:19 2020

$ awk '{printf "%04d%02d%02d%st%sn", $7, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$4)+2)/3, $5, $6, $4" "$5" "$6" "$7}' file | sort -r | head -1
2023040720:09:26        Apr 7 20:09:26 2023

$ awk '{printf "%04d%02d%02d%st%sn", $7, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$4)+2)/3, $5, $6, $4" "$5" "$6" "$7}' file | sort -r | head -1 | cut -f2-
Apr 7 20:09:26 2023

顺便说一下,在你的代码中你有:

awk "{if (i[$3] < $1) i[$3]=$1} END{for(x in i){ print x" "i[x] }}"

你必须转义所有这些符号,因为你使用了错误的引号,因此邀请shell在awk看到脚本之前对其进行解释。只是不要这样做,除非你有特定的理由不这样做:

awk '{if (i[$3] < $1) i[$3]=$1} END{for(x in i){ print x" "i[x] }}'

(对我来说(OP的最终目标还不清楚,所以。。。

假设/理解:

  • 目标#1-打印最新/最新日期
  • 目标#2-打印包含最新/最新日期的行
  • 目标#3-根据日期时间戳对整个输入文件进行排序
  • 所有证书的详细信息都在一行上(即,单个证书的详细内容不跨越多行(
  • 每一行都包含一个格式为"mmm-dd HH:MM:SS yyyy"的日期时间戳

使用GNU awk:的一个想法

awk '   # define field pattern as " mmm dd HH:MM:SS yyyy "
BEGIN { FPAT=" [[:alpha:]]{3} [0-9]{1,2} [0-2][0-9]:[0-5][0-9]:[0-5][0-9] [0-9]{4} "
# build array of months to allow converting from 3-character to numeric
n=split("Jan:Feb:Mar:Apr:May:Jun:Jul:Aug:Sep:Nov:Dec",arr,":")
for (i=1;i<=n;i++)
month[(arr[i])]=i
}
{ n=split($1,arr)                        # split 1st (and only?) FPAT matching field on white space
gsub(/:/," ",arr[3])                   # convert ":" to " "
# convert current datetime stamp to epoch seconds
epoch=mktime(arr[4] " " month[arr[1]] " " arr[2] " " arr[3])
if (epoch > maxepoch +0) {
maxepoch=epoch
dt=$1                               # save current "max" datetime stamp
}
lines[epoch]=$0                        # save current line, indexed by epoch
}
END   { print dt                               # objective #1: print max datetime stamp
print lines[maxepoch]                  # objective #2: print cert line containing max datetime stamp
PROCINFO["sorted_in"]="@ind_num_asc"   # sort array by numeric index in ascending order
for (i in lines)                       # objective #3: print lines[] array in epoch ascending order
print lines[i] > "pki_certs.final.sorted"
}
' cert.dat

注意:

  • 对于a(FPAT、b(mktime()函数和c(PROCinfo["sorted_in"]排序指令需要GNU awk
  • 替换OP的所有当前代码
  • OP可以根据预期结果修改END {...}

这会生成:

# objective #1:
Apr 7 20:09:26 2023
# objective #2:
pki_certs.res:Not After : Apr 7 20:09:26 2023 GMT DNS:MDVARTREPO01.cpp.nonlive
# objective #3:
$ cat pki_certs.final.sorted
pki_certs.res:Not After : May 7 11:58:19 2020 GMT Subject: CN=MDVARTREPO01.cpp.nonlive DNS:MDVARTREPO01.cpp.nonlive
pki_certs.res:Not After : May 7 12:05:44 2020 GMT Subject: CN=MDVARTREPO01.cpp.nonlive DNS:MDVARTREPO01.cpp.nonlive
pki_certs.res:Not After : Apr 8 17:06:54 2021 GMT Subject: CN=MDVARTREPO01.cpp.nonlive DNS:MDVARTREPO01.cpp.nonlive
pki_certs.res:Not After : Apr 9 17:02:43 2021 GMT Subject: CN=MDVARTREPO01.cpp.nonlive DNS:MDVARTREPO01.cpp.nonlive
pki_certs.res:Not After : Apr 9 17:42:27 2021 GMT Subject: CN=MDVARTREPO01.cpp.nonlive DNS:MDVARTREPO01.cpp.nonlive
pki_certs.res:Not After : Apr 17 09:09:35 2021 GMT Subject: CN=MDVARTREPO01.cpp.nonlive DNS:MDVARTREPO01.cpp.nonlive
pki_certs.res:Not After : Apr 12 18:12:02 2022 GMT Subject: CN=MDVARTREPO01.cpp.nonlive DNS:MDVARTREPO01.cpp.nonlive
pki_certs.res:Not After : Apr 7 20:09:26 2023 GMT DNS:MDVARTREPO01.cpp.nonlive

最新更新