문제가 있습니다. 다음 내용이 포함된 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:: 텍스트가 발견될 때마다 이 텍스트 뒤의 값을 다음 함수로 대체하여 해당 타임스탬프를 인식된 형식으로 디코딩하고 싶습니다(한 파일 스캔에서 이 두 값을 대체할 수 있는 경우, 효과가 더 좋습니다) 8GB 파일에 대해 이야기하고 있으며 두 경우 모두 기능이 동일합니다.
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 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 조합이 작동하지 않기 때문에 나는 완전히 길을 잃었습니다.
미리 감사드립니다! ! ! !
답변1
나는 다음과 같은 일을 할 것입니다 :
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'
답변2
다음 접근 방식을 사용할 수 있습니다. 먼저 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
답변3
이해합니다. 올바르게 수행하고 있습니다(sed를 사용하고 Perl에서 hexdump를 사용하는 방법을 모릅니다). 문제는 sed 내에서 이스케이프해야 하는 문자입니다.
이제 두 개의 sed를 실행해야 하지만 완벽하게 작동합니다.
sed 's/\(CSULTIME::\)\(.*\)/echo -n \1" ";echo \2\| 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}'\'' /ge '
sed 's/\(CSLOCTIME::\)\(.*\)/echo -n \1" ";echo \2\| 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}'\'' /ge '
#-------------
Bash 함수에서 코드를 분할하고 내보낸 다음 GNU sed의 ss///e에서 호출할 수 있습니다.
fx() {
printf '%s' "$2" | base64 -d |
hexdump -v -e '1/1 "%02d" ' |
awk -v temp="$1" 'BEGIN {FS = ""} {print temp "20" $5 $6 "-" $3 $4 "-" $1 $2 " " $7 $8 ":" $9 $10 ":" $11 $12}'
}
export -f fx
sed -E "s/((CSULTIME|CSLOCTIME)::\s*)(\S.*)/fx '\1' '\3'/e" file