torr / awk remove newline em duas correspondências padrão

5

Eu tenho um arquivo .pem que depois de alguma formatação é mostrado assim:

-----BEGIN
RSA
PRIVATE
KEY-----
MIIEogIBAAKCAQEAoK3D4mMIRnzPaYqHidgpBnDDzLlcYYd0GoB0pQGyGSHDW7KO3K+VeJP90GhE
ZTEWJLp2N5DR/KT+5Vg7cgdx/GCCrnlbW0McP/IvkYAuWCgbzoXH9eE+kDRtAmurBYCk7OTOwQ26
..........................LONG LONG LONG KEY................................
QRRLFsXua9spUh0yPd163IZStKZMhZBPJfMaqbi1WF+j21DdYyS0qpaZQRjFzRLvGuXeGLZG/COD
ip10XRJMMXY0m14bqOTcqKTya/5PTJIjDWC22+soIjLy0ZjWKo9n05Oal2t4q35kbos=
-----END
RSA
PRIVATE
KEY-----

E eu obviamente preciso ser assim:

-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAoK3D4mMIRnzPaYqHidgpBnDDzLlcYYd0GoB0pQGyGSHDW7KO3K+VeJP90GhE
ZTEWJLp2N5DR/KT+5Vg7cgdx/GCCrnlbW0McP/IvkYAuWCgbzoXH9eE+kDRtAmurBYCk7OTOwQ26
..........................LONG LONG LONG KEY................................
QRRLFsXua9spUh0yPd163IZStKZMhZBPJfMaqbi1WF+j21DdYyS0qpaZQRjFzRLvGuXeGLZG/COD
ip10XRJMMXY0m14bqOTcqKTya/5PTJIjDWC22+soIjLy0ZjWKo9n05Oal2t4q35kbos=
-----END RSA PRIVATE KEY-----

Como posso fazer isso usando awk ou sed ?

Todos os tutoriais que encontrei on-line mostram como fazê-lo para todo o texto ou para um tipo de padrão como aaaabbbaaacccc , o que achei confuso.

Eu tentei algo assim:

tr ' ' '\n' < test.pem  | awk '/BEGIN\nRSA\nPRIVATE\n$/ { printf("%s\t", $0); next } 1' > test-format.pem

Mas isso falhou.

Não sei se é importante ou não, mas estou fazendo isso em um script shell #!/bin/sh em um contêiner do python:3.5-alpine docker.

Qualquer ajuda é muito apreciada.

    
por Fadi 11.07.2016 / 19:44

4 respostas

12

Uma maneira com sed :

sed -e '/^---/ {
  :1
  $!N
  s/\n/ /
  /---$/!b1
}' <file

Essa abordagem faz o trabalho de maneira direta:

  • Se a linha começar com --- , insira o bloco de código
  • Dentro do bloco de código, criamos um rótulo de loop chamado 1
  • Lemos a linha N ext da entrada se a linha atual não for a última linha $
  • Substitua a linha de novo \n por um espaço
  • Se a próxima linha terminar com --- , quebre ! do loop, caso contrário, reinicie o loop b1
por 11.07.2016 / 19:53
3

Suponha que as linhas-chave devam ser coletadas em uma linha longa também:

sed '
    :a
    N
    /\n-\|-\n/{
        P
        D
    }
    s/\n/ /
    ta
    ' file
    
por 11.07.2016 / 20:41
3

Aqui está outro sed :

sed '/^---/,/---$/{H;/^---/h;/---$/!d;x;s/\n/ /g;}' infile

este usa um intervalo e o buffer de espera. Ele anexa cada linha desse intervalo ao buffer de suspensão, sobrescrevendo-a se for o início do intervalo; elimina a linha se não for o fim do intervalo senão troca buffers e substitui todas as novas linhas por espaços.
E uma abordagem diferente com ed :

ed -s infile <<\IN
?^---?,.-s/$/ /
?^---?,$j
1,/---$/-s/$/ /
1,/---$/j
w
q
IN

Este usa quatro intervalos: primeiro ele pesquisa para trás ( ed começa no final do arquivo) e acrescenta um espaço ao final de cada linha no primeiro intervalo e, em seguida, une as linhas no segundo intervalo (que são realmente linhas no primeiro e mais uma linha); em seguida, faz o mesmo, mas a partir do início do arquivo.

    
por 11.07.2016 / 22:12
2

Fazendo a versão posix conforme solicitado no comentário:

#!/bin/sh
jump=1

while IFS= read -r lin; do

  case $lin in 
    ----*)
        jump=0
    ;;
    *----)
        jump=1
    ;;
  esac

  if [ "$jump" = "1" ]; then 
        printf '%s\n' "$lin" 
  else
        printf '%s' "$lin "
  fi

done <"$1"

Para chamar:

./script file.txt >thedest.txt 
    
por 11.07.2016 / 19:55