Вывод действительного файла сертификата из однострочной переменной с bash - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть сертификат, который хранится в переменной среды в одной строке, например:

$EXAMPLE=-----BEGIN CERTIFICATE----- line1 line2 line3 etc.. -----END CERTIFICATE-----

Как перейти из этой среды var в файл, где все строки преобразованы в новые строки,за исключением ----- НАЧАТЬ СЕРТИФИКАТ ----- и ----- КОНЕЦ СЕРТИФИКАТА ----- запчасти?

Я знаю, что могу сделать это:

$ echo "$EXAMPLE" | tr ' ' '\n' > ca.pem

Он заменит все пробелы на новые строки, но это приведет к:

-----BEGIN
CERTIFICATE-----
line1
line2
line3
etc..
-----END
CERTIFICATE-----

Почти там ... но строки BEGIN и END с '-----' не должны прерываться.У кого-нибудь есть чистое решение для этого?Не имеет значения, что это - sed, awk, grep, что угодно:

1013 * Спасибо!

Ответы [ 4 ]

0 голосов
/ 09 декабря 2018

Не могли бы вы попробовать один раз (учитывая, что ваш Input_file такой же, как показанные образцы).

EXAMPLE="-----BEGIN CERTIFICATE----- line1 line2 line3 -----END CERTIFICATE-----"
echo "$EXAMPLE" | awk '
match($0,/- .* -/){
  val=substr($0,RSTART,RLENGTH)
  gsub(/- | -/,"",val)
  gsub(OFS,ORS,val)
  print substr($0,1,RSTART) ORS val ORS substr($0,RSTART+RLENGTH-1)
}'


Объяснение: Добавляем объяснение вышеприведенного кода.

echo "$EXAMPLE" | awk '          ##Printing value of example variable and passing its output to awk command then.
match($0,/- .* -/){              ##using match to match REGEX to match it from - .* to - if match found then do following.
  val=substr($0,RSTART,RLENGTH)  ##creating val here whose value is substring is starting from RSTART to RLENGTH.
  gsub(/- | -/,"",val)           ##Using gsub to substitute to substitute - space OR space - with NULL in variable val.
  gsub(OFS,ORS,val)              ##Substituting OFS with ORS in variable val here.
  print substr($0,1,RSTART) ORS val ORS substr($0,RSTART+RLENGTH-1)  ##Printing substring from 1 to RSTART then val and substring RSTART+RLENGTH-1 with ORS values.
}'
0 голосов
/ 09 декабря 2018

Не используйте все заглавные буквы для неэкспортированных имен переменных, чтобы избежать конфликта с экспортированными и / или встроенными именами.С GNU awk для 3-го аргумента для match () и сокращением \S для [^[:space:]]:

$ example='-----BEGIN CERTIFICATE----- line1 line2 line3 -----END CERTIFICATE-----'
$ printf '%s\n' "$example" |
awk 'match($0,/^(\S+ \S+)(.*)(\S+ \S+)$/,a){gsub(/ /,ORS,a[2]); print a[1] a[2] a[3]}'
-----BEGIN CERTIFICATE-----
line1
line2
line3
-----END CERTIFICATE-----

Приведенный выше скрипт будет работать для любого ввода.Вы должны попытаться придумать входные данные, которые сценарии могут потерпеть неудачу, чтобы иметь возможность протестировать любое предлагаемое решение, чтобы увидеть, работает ли оно на самом деле или нет, так как тривиально создать сценарий, который выдает ожидаемый результат из одного конкретного примера ввода игораздо сложнее найти решение, которое работает во всех случаях.

Например, один важный и очевидный пример для проверки:

$ example='-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- -----END CERTIFICATE-----'

, то есть где в 4-строчном сертификатесамо по себе просто случайно / к сожалению будут эти строки:

  • строка 1 = -----BEGIN
  • строка 2 = CERTIFICATE-----
  • строка 3 = -----END
  • строка 4 = CERTIFICATE-----

Выходные данные должны быть:

$ printf '%s\n' "$example" |
awk 'match($0,/^(\S+ \S+)(.*)(\S+ \S+)$/,a){gsub(/ /,ORS,a[2]); print a[1] a[2] a[3]}'
-----BEGIN CERTIFICATE-----
-----BEGIN
CERTIFICATE-----
-----END
CERTIFICATE-----
-----END CERTIFICATE-----

, поэтому, если какое-либо предлагаемое решение не может обработать это правильно, тогда неt использовать это решение.

Ни один из других опубликованных в настоящее время ответов не обрабатывает его правильно:

awk Равиндера:

$ printf '%s\n' "$example" |
awk '
match($0,/- .* -/){
  val=substr($0,RSTART,RLENGTH)
  gsub(/- | -/,"",val)
  gsub(OFS,ORS,val)
  print substr($0,1,RSTART) ORS val ORS substr($0,RSTART+RLENGTH-1)
}'
-----BEGIN CERTIFICATE-----
-----BEGIN
CERTIFICATE---------END
CERTIFICATE-----
-----END CERTIFICATE-----

saichovsky'sseds plus pipe:

$ printf '%s\n' "$example" |
sed 's/- /-\n/g; s/ -/\n-/g' | sed '/CERTIFICATE/! s/ /\n/g'
-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----END CERTIFICATE-----

anPerl Убхавы:

$ perl -pe 's/(?:BEGIN|END) CERTIFICATE(*SKIP)(*F)|\h+/\n/g' <<< "$example"
-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----END CERTIFICATE-----
0 голосов
/ 09 декабря 2018
echo $EXAMPLE | sed 's/- /-\n/g; s/ -/\n-/g' | sed '/CERTIFICATE/! s/ /\n/g'

должен дать вам то, что вы хотите.

0 голосов
/ 09 декабря 2018

Используя perl, вы можете использовать регулярное выражение с (*SKIP)(*F):

s='-----BEGIN CERTIFICATE----- line1 line2 line3 -----END CERTIFICATE-----'
perl -pe 's/-+(?:BEGIN|END) CERTIFICATE-+(*SKIP)(*F)|\h+/\n/g' <<< "$s"

-----BEGIN CERTIFICATE-----
line1
line2
line3
-----END CERTIFICATE-----

Регулярное выражение ...(*SKIP)(*F)|\h+ пропустит начало -BEGIN CERTIFICATE- или окончание -END CERTIFICATE-при сопоставлении 1+ горизонтальных пробелов, которые должны быть заменены новой строкой.


В случае, если perl не доступно, здесь есть решение awk (небольшое подробное, поскольку я хотел, чтобы оно работало на не-GNUахк):

awk '{
   out=""
   for (i=1; i<=NF; i++)
      out = sprintf("%s%s%s", out, $i, 
      (i<NF && $i~/^-+(BEGIN|END)$/ && $(i+1)~/^CERTIFICATE-+$/ ? " " : "\n"))
   printf "%s", out
}' <<< "$s"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...