Sed

替換文件中的時間戳 Base64 值

  • May 2, 2022

我有一個問題,我有一個文件 test.txt,其內容如下:

dn: serv=CSPS,mscId=167e48dc2b7a42d4acce611c8b477262,ou=multiSCs,dc=three
structuralObjectClass: CP1
objectClass: CP1
objectClass: CUDBServiceAuxiliary
objectClass: CP2
objectClass: CP3
objectClass: CP4
objectClass: CP5
objectClass: CP6
UNKNLOCDATECS:: FQsJ
UNKNLOCDATEPS:: FgMe
ISTTIMESTAMP:: FgMIDyI7
CSULTIME:: HgMWCzYo
CSLOCTIME:: AQQWBA0R
PSULTIME:: HgMWDBco
PSLOCTIME:: HgMWDBco
SCHAR:: AgA=
ICS: 1
CAT: 10
DBSG: 1
OFA: 1
SOCB: 1
PWD: 0000
PWDC: 0
SOCFB: 0

每次找到文本 CSULTIME:: 和 CSLOCTIME:: 時,我想用以下函式替換這些文字之後的值,以將該時間戳解碼為辨識格式(如果我可以在文件的單次掃描中替換這兩個值更好作為我們談論的是 8 GB 文件,兩種情況下的功能相同):

base64 -d | hexdump -v -e '1/1 "%02d" ' | awk 'BEGIN {FS = ""} {print "20" $5 $6 "-" $3 $4 "-" $1 $2 " " $7 $8 ":" $9 $10 ":" $11 $12}'

如果我在 unix 中對這兩個值進行回顯:

For CSULTIME the result would be 2022-03-30 11:54:40: echo -n "HgMWCzYo" | base64 -d | hexdump -v -e '1/1 "%02d" ' | awk 'BEGIN {FS = ""} {print "20" $5 $6 "-" $3 $4 "-" $1 $2 " " $7 $8 ":" $9 $10 ":" $11 $12}'
For CSLOCTIME the result would be 2022-04-01 04:13:17: echo -n "AQQWBA0R" | base64 -d | hexdump -v -e '1/1 "%02d" ' | awk 'BEGIN {FS = ""} {print "20" $5 $6 "-" $3 $4 "-" $1 $2 " " $7 $8 ":" $9 $10 ":" $11 $12}'

因此,最後文件將具有 CSULTIME 和 CSLOCTIME 的這些值:

dn: serv=CSPS,mscId=167e48dc2b7a42d4acce611c8b477262,ou=multiSCs,dc=three
   structuralObjectClass: CP1
   objectClass: CP1
   objectClass: CUDBServiceAuxiliary
   objectClass: CP2
   objectClass: CP3
   objectClass: CP4
   objectClass: CP5
   objectClass: CP6
   UNKNLOCDATECS:: FQsJ
   UNKNLOCDATEPS:: FgMe
   ISTTIMESTAMP:: FgMIDyI7
   CSULTIME:: 2022-03-30 11:54:40
   CSLOCTIME:: 2022-04-01 04:13:17
   PSULTIME:: HgMWDBco
   PSLOCTIME:: HgMWDBco
   SCHAR:: AgA=
   ICS: 1
   CAT: 10
   DBSG: 1
   OFA: 1
   SOCB: 1
   PWD: 0000
   PWDC: 0
   SOCFB: 0

我完全迷失了,因為我嘗試 sed 的所有組合都無法使它們起作用。

提前致謝!!!!

我會做類似的事情:

perl -MMIME::Base64 -pe 's{^[^:]*TIME:\K: (\S+)}{
 my ($d, $m, $y, @t) = unpack "C*", decode_base64 $1;
 sprintf "20%02d-%02d-%02d %02d:%02d:%02d", $y, $m, $d, @t}e'

您可以使用以下方法,我們首先設置用於 base64 解碼的工具,然後使用 GNU sed 處理編碼數據。

#------------------
#  base64 in sed
#------------------
set -u

#> present century
century=$(date '+%C')

#> format string printf
fmt='%s%s\n'

#> bit, sextet, & octet regex
bit='[01]'
sextet="${bit}{6}"
octet="${bit}{8}"; byte=$octet

#> base64 charset
b64='/[:alnum:]+'
declare -a b64_chars=({A..Z} {a..z} {0..9} + /)

#> user-defined helper function(s)
oneLine() {
 # collapse stdin into one line
 paste -sd'\0' -
}

esc_rhs() {
 # make stdin pkuggable
 # on the rhs of a s///
 sed -e '
   s:[\/&]:\\&:g
   $!s:$:\\:
 ' -
}

dec2bin() {
 # create an array of size 2^$1
 # Usage: dec2bin 6
 # creates array d2b as:
 # underscore for clarity only
 # $d2b[0] => "000_000"
 # $d2b[1] => "000_001"
 #        ...
 # $d2b[63] => "111_111"

 eval "d2b=($(yes '{0,1}' | sed "$1q" | oneLine))"
}

#> build the encoding lookup table
encode_tbl=$(printf '%s\n' "$(
dec2bin 6
i=0
for c in "${b64_chars[@]}"
do
 printf "$fmt" "$c" "${d2b[$i]}"
 (( i++ ))
done
)" | esc_rhs)

#> build the decoding lookup table
decode_tbl=$(printf '%s\n' "$(
dec2bin 8
for dec in {0..255}
do
 hex=$(printf '%02x' "$dec")
 bin=${d2b[$dec]}
 printf "$fmt" "$bin" "$hex"
done
)" | esc_rhs)

#> hex to bin
h2d=$(for i in {0..255};do
 printf 'x%02x:%02d\n' "$i" "$i"
done | oneLine | esc_rhs)

#######> main()
sed -E "
 s/^\s*(CSULTIME|CSLOCTIME)::\s*/&\n/;T
 h;s/\n.*//
 x;s/.*\n//
 s/[^${b64}]//g
 /^\$/d;s/^|\$/\n/g

 # unencode
 s/\$/$encode_tbl/
 :encode
 /\n\n/!{
   s/((\n)[${b64}])(.*\1(${sextet}))/\4\2\3/
   b encode
 }

 s/\n.*//;:pad
 /^(${octet})+\$/!{
   s/\$/0/;b pad
 }
 # chunk it in 8-bit portions
 s/(${octet})/& /g
 G;s/\$/${decode_tbl}/;t decode
 :decode
   s/(${octet}) (.*\n\1([[:xdigit:]]{2}))/\3\2/
 t decode
 s/\n.*//

 #> hex to decimal
 s/^|\$/\n/g
 s/\$/$h2d/;t hex2int
 :hex2int
 s/\n([[:xdigit:]]{2})(.*\n.*x\1:([[:digit:]]+))/\3\n\2/
 t hex2int
 s/\n.*//

 #> rearrange decoded value into
 #> yyy-mm-dd hh:mm:ss format
 s/(..)(..)(..)/\3\2\1/
 s/../&-/g
 s/(.*)./$century\1/
 s/-/:/3g
 s/:/ /

 #> stitch back the prefixes
 #> CSULTIME, CSLOCTIME
 H;z;x;s/\n//
" file

輸出:-

-1e-0===
dn: serv=CSPS,mscId=167e48dc2b7a42d4acce611c8b477262,ou=multiSCs,dc=three
structuralObjectClass: CP1
objectClass: CP1
objectClass: CUDBServiceAuxiliary
objectClass: CP2
objectClass: CP3
objectClass: CP4
objectClass: CP5
objectClass: CP6
UNKNLOCDATECS:: FQsJ
UNKNLOCDATEPS:: FgMe
ISTTIMESTAMP:: FgMIDyI7
CSULTIME:: 2022-03-30 11:54:40
CSLOCTIME:: 2022-04-01 04:13:17
PSULTIME:: HgMWDBco
PSLOCTIME:: HgMWDBco
SCHAR:: AgA=
ICS: 1
CAT: 10
DBSG: 1
OFA: 1
SOCB: 1
PWD: 0000
PWDC: 0
SOCFB: 0

引用自:https://unix.stackexchange.com/questions/700734