Como faço para procurar um arquivo por uma string e usá-lo como uma variável?

0

Eu tenho um arquivo XML que se parece com isso:

<id>456</id>

<root>
<value>1</value>
<intNum>2</intNum>
</root>

<root>
<eulav>1</eulav>
<muNtni>2</muNtni>
</root>   

Eu quero lembrar de <id>456</id> e fazer isso:

sed 's/\<root\>/\
\<root\> 
$herecomestheid

Basicamente, o que isto faz é substituir <root> por <root>\n<id>456</id> . \n neste caso significa nova linha. Eu já sei disso, mas o problema que estou tendo é lembrar <id>456</id> e mantê-lo pronto para uso posterior.

Eu tentei isso (o que obviamente não funcionou):

 sed -i '' 's/\<root\>/\
 \<root\>\
 \<id\>.\<\/id\>/g'

e eu tentei fazer algo assim:

cat file.xml | grep '\<id\>*\<\/id\>'

E tentei transformar a saída grep em uma variável. E isso obviamente não funcionou também.

EDIT: <id>*</id> está supostamente na raiz.

    
por DisplayName 02.11.2014 / 02:34

3 respostas

4

O processamento de XML como texto geralmente não é uma solução robusta, mas se você insistir em fazê-lo, talvez possa usar o espaço de armazenamento do sed , por exemplo

sed -e '/<id>[0-9]*<\/id>/h' -e '/<root>/{x;p;x;}' file.xml
    
por 02.11.2014 / 03:18
1
sed -e :b -e '$!{N;\|<id>.*\n<root>|!bb
};do what ever you want to do with all of those lines now....'

Concordo com a steeldriver que h oldspace é provavelmente a melhor aposta, mas há outras opções. Às vezes, não podemos nos incomodar em gerenciar os dois buffers - ou, como geralmente é problema meu - já estamos gerenciando os dois buffers. O trecho acima empilha linhas no espaço padrão. Contanto que sempre ocorra entre <id> tags, ele preencherá recursivamente o espaço padrão com o bloco de dados desejado antes de prosseguir para a linha 2 - isto é, ele fará isso enquanto os buffers não implodem enquanto isso - mas isso é algo difícil de fazer hoje em dia .

Além disso, voltando à parte do h old space, e x change realmente troca h old e space space. Usá-lo uma vez renderiza o buffer padrão como o buffer h old e vice-versa. Este efeito sobrevive aos ciclos de linha. Muitas vezes, o que eu faço é ler um arquivo até chegar a uma linha inicial, realizar edições preliminares, depois trocar e manter H olding até obter outra. Quando meu script troca de volta, acaba em um bloco atrás - no último marcador que eu liguei, além de tudo, H eld enquanto isso. É uma maneira simples de armazenar apenas o máximo que for necessário.

E assim, outra maneira de implementar um loop como você deseja fazer é:

sed -e '/<id>/h;//!H;/<root>/!{$!d' -e '};x...'

A partir desse ponto, seu espaço de padrão é H old space e vice-versa. h old irá sobrescrever h espaço antigo com o espaço padrão atual sempre que for usado - então o exemplo acima inicia um novo buffer com uma linha <id> todas as vezes. !H acrescenta todas as linhas intermediárias a H old space, cada uma seguindo um caractere \n ewline. $!d elimina o espaço padrão em cada linha que é ! , não a $ última, quando a linha atual estiver com segurança H eld e inicia o próximo ciclo de linha e, portanto, a alteração x ocorre apenas em <root> corresponde ao momento em que o bloco inteiro está esperando por você.

Lembre-se apenas que, no seu bloco último , o marcador é provavelmente a última linha, caso seja diferente das correspondências <root> .

Mas ...

De acordo com sua edição, não vejo nenhum motivo pelo qual você não possa se safar:

sed '/<id>/h;//d;\|</root>|G
' <<\INPUT
unimportant 1
<id> number 1 </id>
<root> sub text
more text
 more text
</root>
<root> sub text as well
and more text
and more text
</root>
unimportant 2
<id> number 2 </id>
<root> sub text
more text
more text
</root>
<root> sub text
and more text
and more text
</root>
INPUT

<id> linhas são h eld (novamente: sobrescrevendo h espaço antigo) e, em seguida, d da saída. Quando ocorre uma coincidência </root> , sed G define o espaço h old anexado ao espaço padrão antes de imprimir automaticamente os resultados no final do ciclo de linha, que se parece com:

unimportant 1
<root> sub text 
more text
 more text
</root>
<id> number 1 </id>
<root> sub text as well
and more text
and more text
</root>
<id> number 1 </id>
unimportant 2
<root> sub text
more text
more text
</root>
<id> number 2 </id>
<root> sub text
and more text
and more text
</root>
<id> number 2 </id>
    
por 02.11.2014 / 04:29
0

Uma solução usando awk seria

awk '/<id>/{id=$0}/<root>/{print id}1' file.xml

Se você não quiser imprimir a linha <id> , pule essa linha adicionando next .

awk '/<id>/{id=$0;next}/<root>/{print id}1' file.xml
    
por 02.11.2014 / 03:28