comando simples para remover cabeçalho e rodapé de um arquivo

4

Eu quero um comando para remover um cabeçalho e rodapé XML de um arquivo:

<?xml version="1.0" encoding="UTF-8"?>
<conxml>
<MsgPain001>
    <HashValue>A9C72997C702A2F841B0EEEC3BD274DE1CB7BEA4B813E030D068CB853BCFECA6</HashValue>
    <HashAlgorithm>SHA256</HashAlgorithm>
    <Document>
                ...
    </Document>
    <Document>
                ...
    </Document>
</MsgPain001>
</conxml>

...

Deve se tornar apenas

<Document>
         ...
    </Document>
    <Document>
          ...
    </Document>

(observe o recuo, o recuo da primeira etiqueta do documento deve ser removido.

Isso soa como um regex (ganancioso)

<Document>.*</Document>

Mas eu não entendo isso devido aos feeds de linha.

Eu preciso disso em um pipe para calcular um hash sobre os documentos contidos.

    
por Bastl 20.10.2011 / 15:34

2 respostas

6

Usando sed :

 sed -n '/<Document>/,/<\/Document>/ p' yourfile.xml

Explicação:

  • -n torna sed silent, o que significa que não produz o conteúdo completo do arquivo,
  • /pattern/ procura por linhas que incluem um padrão especificado,
  • a , b (a vírgula) diz a sed para executar uma ação nas linhas de a a b (onde a e b são definidos pela correspondência dos padrões acima),
  • p significa impressão e é a ação executada nas linhas que correspondem ao acima.

Editar: Se você gostaria de extrair o espaço em branco antes de <Document> , isso pode ser feito assim:

 sed -ne '/ <Document>/s/^ *//' -e '/<Document>/,/<\/Document>/ p' yourfile.xml
    
por 20.10.2011 / 15:45
1

Para evitar que o texto seja dividido entre </Document> e o próximo <Document> , talvez seja necessário usar uma série de comandos sed (cf. comentário de Gilles acima).

Essencialmente sed lê todo o arquivo no buffer de suspensão (para que o conteúdo do arquivo possa ser tratado como uma única linha) e marca o primeiro e o último Document tags para processamento posterior.

# version 1
# marker: HERE
cat file.xml | 
sed -n '1h;1!H;${;g;s/\(<Document>.*<\/Document>\)/HEREHERE/g;p;}' | 
sed -n -e '/HERE<Document>/,/<\/Document>HERE/ p' | 
sed -e 's/^ *HERE\(<Document>\)//' -e 's/\(<\/Document>\)HERE *$//'

# version 2    (using the Bash shell)
# marker: $'
# version 1
# marker: HERE
cat file.xml | 
sed -n '1h;1!H;${;g;s/\(<Document>.*<\/Document>\)/HEREHERE/g;p;}' | 
sed -n -e '/HERE<Document>/,/<\/Document>HERE/ p' | 
sed -e 's/^ *HERE\(<Document>\)//' -e 's/\(<\/Document>\)HERE *$//'

# version 2    (using the Bash shell)
# marker: $'%pre%1'
cat file.xml | 
sed -n $'1h;1!H;${;g;s/\(<Document>.*<\/Document>\)/%pre%1\1%pre%1/g;p;}' | 
sed -n -e $'/%pre%1<Document>/,/<\/Document>%pre%1/ p' | 
sed -e $'s/^ *%pre%1//' -e $'s/%pre%1 *$//' | 
cat -vet
1' cat file.xml | sed -n $'1h;1!H;${;g;s/\(<Document>.*<\/Document>\)/%pre%1\1%pre%1/g;p;}' | sed -n -e $'/%pre%1<Document>/,/<\/Document>%pre%1/ p' | sed -e $'s/^ *%pre%1//' -e $'s/%pre%1 *$//' | cat -vet

... mas acho que tudo isso poderia ser feito de forma mais elegante (e confiável) usando xmlstarlet !

    
por 21.10.2011 / 14:48