Inserir linhas após o jogo de várias linhas Regex

4

Eu tenho um arquivo XML que preciso anexar depois de um conjunto específico de tags. Basicamente, a estrutura do arquivo é assim:

<key>servers</key>
<dict>
... Server Details ...
</dict>

Gostaria de combinar nas linhas:

<key>servers</key>
<dict>

e acrescente um bloco de XML especificando uma conexão de servidor imediatamente após <dict> . Eu tenho o novo bloco XML em seu próprio arquivo de texto, pois é bastante longo.

Eu olhei para sed e awk para fazer isso, mas enfrentei uma parede. Eu também vi exemplos de usar perl para realizar isso, mas eu não estou tão familiarizado com Perl. Pelo que entendi, sed e awk não são ótimos na correspondência de várias linhas.

A razão pela qual preciso fazer a correspondência de várias linhas é porque a tag <dict> é usada com frequência no arquivo XML e eu preciso anexar um bloco à seção <key>servers</key> , em vez de substituir todo o seu conteúdo.

    
por user80235 08.08.2014 / 19:45

5 respostas

3

Você pode fazer algo como:

awk '{print}
     $0 == "<dict>" && previous == "<key>servers</key>" {
       system("cat other-file.xml")
     }
     {previous = $0}'
    
por 08.08.2014 / 19:49
3
sed '/keys_line_1/,/keys_line_last/{/keys_line_last/{
h;s/unique_split_point.*//;r /path/to/insert/file
x;s/.*unique_split_point//;G
}}'

sed não é exatamente indulgente quando se trata de exigir ajustes em uma hipótese. Tudo que o sed faz é um resultado direto da coisa que acabou de fazer, e, portanto, um erro muito pequeno em detalhes pode alterar drasticamente os resultados.

Desta forma, sem um pouco de loucura e muita paciência, a depuração de scripts sed pode ser um assunto frustrante, mas, dadas essas qualidades, as recompensas podem ser significativas. Eu altamente recomendo usar o comando l ook durante o processo, tanto quanto você faria se tentasse.

sed ...;l;...complicated_script...;l;...

Na verdade, olhando uma segunda vez para a sua pergunta, e acho que é mais fácil do que assumi inicialmente. Tudo o que você realmente precisa (eu acho) é expandir o espaço padrão por uma linha em um caso de correspondência servidores . Por padrão, sed armazena apenas uma linha por ciclo, mas os comandos N , P e D fornecem controle direto sobre esse comportamento.

Na verdade, acredito que entendi mal a questão originalmente - embora você queira inserir um texto em uma linha, não em um bloco de linhas.

Então você talvez precise:

sed '\|<key>servers</key>|,/<dict>/N;P
/\n<dict>/!D;s/.*\n//;r /path/to/file'

Dessa forma, todas as linhas, exceto aquelas em que você está interessado - o intervalo de seu servidor por sua correspondência dict é eliminado do buffer de edição assim que possível , e você apenas r de seu arquivo de destino após a primeira correspondência dict que segue qualquer sequência de seu * servidor, e o único ponto em que arquivo é sempre anexado o buffer de saída segue diretamente sua correspondência dict se for precedido por um \n ewline.

    
por 08.08.2014 / 21:07
1

Algo parecido com este trabalho?

sed '\|<key>servers</key>|{n
\|<dict>| r other-file.xml
}' file.xml
    
por 08.08.2014 / 21:12
0

Você poderia ser um pouco mais específico sobre o resultado esperado? Eu usaria python3 e um

PATH = '/My/Path/'

FILE = 'MyFile.xml'

for i, line in enumerate(open(PATH+FILE, 'r')):

... # 

já que é fácil pegar um \n , e uma linha termina com um, então encontrar as linhas que você está procurando é fácil

mas preciso de uma melhor compreensão do resultado para continuar

    
por 08.08.2014 / 23:48
0

Desde que você adicionou uma tag Perl:

perl -pE 'BEGIN{
              $/ = "<key>servers</key>\n<dict>\n"; 
              $content = 'cat file.xml'
          }
          $_.=$content' your_input_file
    
por 11.08.2014 / 01:13