Você pode fazer algo como:
awk '{print}
$0 == "<dict>" && previous == "<key>servers</key>" {
system("cat other-file.xml")
}
{previous = $0}'
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.
Você pode fazer algo como:
awk '{print}
$0 == "<dict>" && previous == "<key>servers</key>" {
system("cat other-file.xml")
}
{previous = $0}'
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.
Algo parecido com este trabalho?
sed '\|<key>servers</key>|{n
\|<dict>| r other-file.xml
}' file.xml
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
Desde que você adicionou uma tag Perl:
perl -pE 'BEGIN{
$/ = "<key>servers</key>\n<dict>\n";
$content = 'cat file.xml'
}
$_.=$content' your_input_file