SED copia seção específica para arquivos diferentes

1

Eu tentei criar um script que economiza meu tempo. Isso é o que eu quero fazer: Eu tenho um grande arquivo .xml com seções, digamos que se parece com isso:

some text
.....
HEAD
context A
TAIL
some text
.....
HEAD
context B
TAIL
....
some text
....
HEAD
context C
TAIL
....
some text

Eu preciso cortar a seção com context A e passar para o arquivo contextA, depois context B para o arquivo contextB e assim por diante. (Todos os arquivos devem conter a sintaxe HEAD context x TAIL ) O problema é que todos os contextos começam e terminam no mesmo regex (HEAD e TAIL). Eu posso cortar toda a seção em um arquivo, mas não é o suficiente.

Você pode me ajudar?

É uma pequena atualização porque talvez eu não esteja esclarecido o suficiente: Vamos dizer que meu arquivo é assim:

 some text 1
 <config>
 1
 2
 3
 </config>
 some text 2
 <config>
 4
 5
 6
 </config>
 some text 3
 <config>
 7
 8
 9
 </config>
 some text 4

e eu quero arquivo chamado:

"primeiro" que contém:

 <config>
 1
 2
 3
 </config>

"second", que contém:

 <config>
 4
 5
 6
 </config>

e assim por diante.

    
por TomM 16.01.2018 / 22:38

4 respostas

1

É mais fácil fazer isso com o awk:

awk -v RS="HEAD\n" -v FS="\n" 'NR>1{print "HEAD\n" $0 > $1".txt"}' ex

Notas:

  • RS="HEAD\n" registradores são separados por "HEAD \ n"
  • FS="\n" cada campo é uma linha
  • NR>1{print "HEAD\n" $0 > $1} para todos os registradores, exceto o primeiro, escreva-os em um arquivo chamado campo 1 - "$ 1"

UPDATE: para a nova pergunta:

awk -v RS="<config>\n" -F"</config>" 'NR>1{print RS $1 FS > "conf-"NR-1}' ex

As saídas de configuração são armazenadas em arquivos com o nome: "conf-1"

    
por JJoao 17.01.2018 / 09:49
1

Meu script usando awk :

#!/bin/bash
for i in $(seq -w $(<"$1" grep -cx "$2")); do
  <"$1" >$i awk -va=$i -vb="$2" -vc="$3" '$0~b{d++;e=1}d==a&&e==1;$0~c{e=0}'
done

Salvar como, por exemplo, myscript.sh , torne-o executável, navegue até seu onebig.xml e chame assim:

/path/to/myscript.sh onebig.xml HEAD TAIL

Ele cortará todas as seções de onebig.xml , começando com HEAD e terminando com TAIL , e as salvará como 1 , 2 ,… se houver menos de 10 seções, como 01 , 02 ,… se houver 10 a 99 seções, como 001 , 002 ,… se houver 100 a 999 seções e assim por diante.

Explicações breves

  • <"$1" grep -cx "$2" - conta ocorrências de HEAD em onebig.xml , digamos que é 3
  • for i in $(seq -w 3); do …; done - percorre todas as ocorrências de 1 a 3 , seq a opção -w adiciona zeros à direita, se necessário
  • <"$1" >$i - leu onebig.xml e escreveu em um arquivo com o nome da contagem atual
  • awk -va=$i -vb="$2" -vc="$3" - inicie awk e atribua três variáveis, a sendo a contagem, b sendo HEAD e c sendo TAIL
  • $0~b{d++;e=1} - se a linha atual contiver o conteúdo de b (= HEAD ), aumente d em um e defina e=1
  • d==a&&e==1 - se d for igual a a (= a contagem atual) e e for igual a 1 , em seguida, imprima a linha atual ( print é a ação implícita; essencialmente é: se for após a a a ocorrência de HEAD e estamos entre HEAD e TAIL e depois imprimimos)
  • $0~c{e=0} - se a linha atual contiver o conteúdo de c (= TAIL ), defina e=0
por dessert 17.01.2018 / 08:58
1

Se você realmente não pode usar um analisador XML adequado para isso , sugiro awk , por exemplo,

awk '/^HEAD/ {p=1; ++n} p {print > "context"n} /^TAIL/ {p=0}' file.xml

produzirá as seções HEAD ... TAIL em nomes de arquivos numericamente crescentes context1 , context2 etc.

Para uma classificação mais fácil, você pode querer melhorar um pouco construindo um prefixo numérico de largura fixa, por exemplo,

$ awk '/^HEAD/ {p=1; outfile = sprintf("context%03d", ++n)} p {print > outfile} /^TAIL/ {p=0}' file.xml

$ head context*
==> context001 <==
HEAD
context A
TAIL

==> context002 <==
HEAD
context B
TAIL

==> context003 <==
HEAD
context C
TAIL
    
por steeldriver 17.01.2018 / 16:20
0

Por favor, verifique se o script abaixo ajuda você a:

#!/bin/bash
for x in {A..Z}; do
    # check if the pattern exists in the file
    if grep -qF "context $x" file.txt; then
        # Store the lines between the 2 patterns including the matching lines in a text file
        awk '/context '$x'/,/TAIL/' file.txt > context$x.txt
    else
       echo "Sorry this pattern does not exists in file"
    fi
done
    
por Rajesh Keladimath 17.01.2018 / 07:13