Преобразование текстового представления временного интервала в сценарии оболочки

Ключи ssl(частный и открытый )обычно хранятся в так называемом формате PEM .

Privacy-Enhanced Mail (PEM) is a de facto file format for storing and sending cryptographic keys, certificates, and other data, based on a set of 1993 IETF standards defining "privacy-enhanced mail." While the original standards were never broadly adopted, and were supplanted by PGP and S/MIME, the textual encoding they defined became very popular. The PEM format was eventually formalized by the IETF in RFC 7468.

Этот формат на самом деле является заголовком, затем base64 закодированными двоичными данными и нижним колонтитулом.

Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. The term Base64 originates from a specific MIME content transfer encoding. Each Base64 digit represents exactly 6 bits of data. Three 8-bit bytes (i.e., a total of 24 bits) can therefore be represented by four 6-bit Base64 digits.

Ключи sshсм. ниже от Дэйва _Томпсона _085 комментариев:

Note ssh-keygen uses (several) PEM formats but never the one(s) in 7468. In the past for RSA it defaulted to OpenSSL's two 'traditional' (aka 'legacy') formats, either unencrypted whcih is 7468-like except containing PKCS1, or password-encrypted which is1421-like with Proc-type and DEK-Info and base64 of encrypted PKCS1, but not 7468-like. Since 7.8 it defaults to OpenSSH's own 'new format' (previously invoked by option -o) which is 7468-like but the contents are entirely different (XDR-style not ASN.1). There are numerous Qs about these already on several Stacks.

OpenSSH public key formats are never PEM (although commercial 'SSH2' sort-of are), just base64 of SSH wire format. And I was recently reminded this Q/A covers the private key formats quite thoroughly

2
11.03.2021, 16:20
7 ответов

Поскольку кажется, что вы хотите преобразовать только «текстовое представление», вы можете направить вывод команды через sed. Следующая команда сначала удаляет ns, а затем заменяет sна .:

.
~$ echo "2s576039936ns" | sed -e 's/ns//' -e 's/s/./'
2.576039936

Обновление

В комментарии вы заявили, что наносекундная часть не равна нулю -дополнена точно до 9 цифр. В этом случае вывод будет неверным. К исправлению,вы можете использовать следующее awkрешение:

~$ echo "2s576039936ns" | awk -F'n?s' '{printf "%d.%09d\n",$1,$2}'

Будет использоваться sили nsв качестве разделителя полей (многосимвольные -разделители полей символов будут интерпретироваться как регулярное выражение, а не просто как многосимвольная -символьная строка )и поля печати один и два (последний теперь ноль -дополнен до 9 знаков после запятой )с .в качестве разделителя.

Таким образом, в вашем скрипте вы можете использовать

t=$( your_command | awk -F'n?s' '{printf "%d.%09d\n",$1,$2}' )
1
18.03.2021, 22:27

Вы можете использовать эту функцию Bash (не уверен, что это POSIX):

x=2s576039936ns
y=${x/s/.}
z=${y/ns/}
echo $z

илиsed:

echo 2s576039936ns | sed 's/s/./; s/ns//'

Оба метода сначала заменяют s точкой, а затем удаляют ns.

И совершенно другое:

echo 2s576039936ns | awk -F '[ns]' '{print $1 "." $2}'

Предполагается, что вы хотите изменить только формат , а не числа.

6
18.03.2021, 22:27

, если также используется awk,:

awk -F'n?s' '$0=$1"."$2'

n?s, определенный как разделитель полей, устанавливает обе строки nsили sв качестве FS; это ERE, что означает необязательный n, за которым следует символ s, который каждый awk поддерживает определение FS как расширенное регулярное выражение.

2
18.03.2021, 22:27

Это решение будет обрабатывать 2s576039936ns, а также 2s123ns:

.
$ echo 2s576039936ns | tr '[:alpha:]' ' ' | awk -- '{ printf "%d.%09d",$1,$2 }'
2.576039936

$ echo 2s123ns | tr '[:alpha:]' ' ' | awk -- '{ printf "%d.%09d",$1,$2 }'
2.000000123
7
18.03.2021, 22:27

Сperl:

$ echo 10000s12576039936ns 1s1ns 0001s1000000ns 12s0ns |
   perl -Mbignum -pe 's{(\d+)s(\d+)ns}{$1 + $2 / 1e9}ge'
10012.576039936 1.000000001 1.001 12

Обратите внимание, что произвольная точность (здесь с использованием bignumвperl)обычно требуется при работе со значениями секунды + наносекунды в арифметических операциях, как в struct timespec, управляемом clock_gettime(), например, если вы хотите сохраняйте точность до наносекунды, поскольку тип doubleвашего процессора/компилятора C, обычно используемый инструментами, выполняющими арифметические операции (awk, perlбез bignum, оболочек... ), не имеет достаточной точности.

Сzsh:

string='10000s12576039936ns 1s1ns 0001s1000000ns 12s0ns'

set -o extendedglob
newstring=${string//(#b)(<->)s(<->)ns/\
$((match[1] + match[2] / 10**9))${${:-.${(l[9][0])match[2]}}%%(.|)0#}}

Дает вам 10012.576039936 1.000000001 1.001 12в $newstring, а также (здесь, используя целочисленную арифметику для двух чисел, поскольку zshтакже использует doubleдля своих чисел с плавающей запятой ).

4
18.03.2021, 22:27

Еще пара способов вbash:

Для этой конкретной цели эта работа:

echo "${value%%s*}.${value:2:${#value}-4}"

Для аналогичного случая, но с большей точностью для действительной части целого числа:

[[ $value =~ ^([[:digit:]]+)s([[:digit:]]+)ns$ ]]
new_value="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
1
18.03.2021, 22:27

В оболочке POSIX -или bashв этом отношении -вы не можете преобразовать число за один шаг. Здесь я заменил sдесятичной точкой, а затем удалил ns

.
v='2s576039936ns'

t="${v%%s*}.${v#*s}"
t="${v%ns}"

echo "$t"
2.576039936

Вы пометили , так что вы можете немного упростить, но это все равно займет два шага

v='2s576039936ns'

t="${v%ns}"
t="${t/s/.}"

echo "$t"
2.576039936

В качестве альтернативы можно перейти к внешней команде и выполнить все за один шаг

v='2s576039936ns'

t=$(echo "$v" | sed -E sed -E 's/([[:digit:]]+)s(([[:digit:]]+)ns)?/\1.\3/')

echo "$t"
2.576039936
0
18.03.2021, 22:27

Теги

Похожие вопросы