Obter valores bloco por bloco no mesmo arquivo

3

Eu tenho um arquivo dizendo "SAMPLE.txt" com o seguinte conteúdo,

P1
10,9:6/123456
P2
blah blah
P1
10,9:5/98765
P2
blah
blah
P1
blah blah
P2

Eu quero que um arquivo de saída diga "RESULT.txt" como,

Value1:123456
Value2:98765
Value3:NULL

Primeiro preciso buscar conteúdo entre P1 e amp; P2 parte, então eu quero encontrar o valor de 10,9 * / que eu quero salvar em outro valor. Caso algum bloco P1 - P2 não contenha este valor, eu quero salvá - lo como "NULL".

Como posso codificar os itens acima em shell / awk?

Sou muito novo no script.

    
por Garvit Khandelwal 09.06.2014 / 19:35

5 respostas

2

Isso funciona e é totalmente portátil:

sed '\|^P1.*|!d;s||Value:|
     :n
     N;\|\nP2|!bn
     s|:.*\n10,9[^/]*/|:|
     s|\n.*||;s|:$|:NULL|' 

O fluxo funciona assim:

  1. Primeiro, ele aborda uma linha ^ começando com P1

  2. Se a linha atual ! não corresponder a ela, d a elimina.

  3. Se isso acontecer, substitui P1 por Value:

  4. Em seguida, ele define o rótulo :n ext e extrai a linha N ext.

  5. Se \nP2 for ! , não encontrei b ranches de volta ao rótulo :n ext e tente novamente repetidamente até ocorrer.

  6. Em seguida, exclui qualquer ocorrência de :.*\n10,9 até o primeiro caractere / .

  7. Exclui o primeiro ewline \n disponível e todos os caracteres a seguir.

  8. Se o último caractere for o : dois pontos após Value , ele insere a string NULL .

As etapas 6 e 7 são o que o faz funcionar - em 6, ele exclui o \n ewline que precede a sequência de números desejada, mas se isso não estiver lá, o próximo \n ewline será o imediatamente seguinte Value: so tudo vai no passo 7.

Aqui está em ação:

sed '\|^P1.*|!d;s||Value:|
     :n
     N;\|\nP2|!bn
     s|:.*\n10,9[^/]*/|:|
     s|\n.*||;s|:$|:NULL|' <<\DATA
P1
10,9:6/123456
P2
blah blah
P1
10,9:5/98765
P2
blah
blah
P1
blah blah
P2
DATA

OUTPUT:

Value:123456
Value:98765
Value:NULL
    
por 09.06.2014 / 20:07
2

Com perl (retira todo o arquivo na memória):

 perl -0777 -ne 'while (/P1\n(.*?)\nP2/gs) {
   printf "Value%d:%s\n", ++$n, $1 =~ /^10,9.*\// ? $'\'': "NULL"}'
    
por 09.06.2014 / 22:01
1

Uma solução perl :

$ perl -F'/' -alne '
    if (/P1/../P2/ and $_ !~ /^P/) {
        print "Value@{[++$i]}:",$F[1]?$F[1]:"NULL";
    }
' file
Value1:123456
Value2:98765
Value3:Null

Uma solução awk :

$ awk -F'/' '/P2/{f=0};/P1/{f=1;next};f{print "Value"++i":"($2?$2:"Null")}' file
Value1:123456
Value2:98765
Value3:Null
    
por 09.06.2014 / 20:03
1

Outra solução awk :

$ awk '$0=="P1" {f=1} $0=="P2" {f=0}f' file | paste - - | \
    awk -F"\t" '$2~/[0-9]/ {split ($2,a,"/"); \
    print "Value"NR":"a[2]} $2!~/[0-9]/ {print "Value"NR":NULL"}'
Value1:123456
Value2:98765
Value3:NULL
    
por 09.06.2014 / 20:19
0

Muito obrigado pessoal. Essa é a parte do código que finalmente resolveu meu problema.

nawk -v fname="${filename}" -F '/|:' '

    function isnum(x){return(x==x+0)}

    /P1/,/P3/{
            # Found start increment i reset variables go to next line
            if(/P1/){
                   ++i 
                   fid ="" 
                   count++
                   next
                }

            # Found end validate variable and print go to next line
            if(/P3/){
                printf "%s|",count
                printf "%s|",isnum(fid)?fid:"NULL"
                  next 
                }
            if(!fid && /36,59:*/)
                {
                    fid = $NF
                }
        ' ${filename} >>output.txt

Mas agora estou tendo outro problema para o qual criei um segmento separado.

Aqui está o link se vocês puderem ajudar.

link

    
por 18.06.2014 / 06:47