Analisando um arquivo usando ferramentas de processamento de texto

5

Um arquivo parece:

1140.271257 0.002288454025 0.002763420728 0.004142512599 0 0 0 0 0 0 0 0 0 0 0 
1479.704769 0.00146621631 0.003190634646 0.003672029231 0 0 0 0 0 0 0 0 0 0 0 
1663.276205 0.003379552854 0.04643209167 0.0539399155 0 0 0 0 0 0 0 0 0 0 0 0 

Posso usar alguma ferramenta de processamento de texto para dividi-la em dois arquivos, como:

1:

1140.271257 0.002288454025 0.002763420728 0.00414251259
1479.704769 0.00146621631 0.003190634646 0.003672029231
1663.276205 0.003379552854 0.04643209167 0.0539399155

2:

0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 

Basta pegar os primeiros números, que não são 0, e depois colocar o resto em outro arquivo ... se o arquivo puder ser nomeado como o nome do arquivo original com x1 e x2 ou algo assim, seria legal.

    
por heineman 09.09.2015 / 10:53

6 respostas

6

com awk . O comando abaixo verifica cada entrada em cada linha e grava em arquivos diferentes, no meu exemplo out1 e out2 . Se houver uma nova linha no arquivo de entrada, também uma nova linha será gravada no arquivo de saída.

awk '{for(i=1;i<=NF;i++) {if($i!=0) {printf "%s ",$i > "out1"} else {printf "%s ",$i > "out2"}; if (i==NF) {printf "\n" > "out1"; printf "\n" > "out2"} }}' foo

Exemplo

O arquivo de entrada

cat foo

1140.271257 0.002288454025 0.002763420728 0.004142512599 0 0 0 0 0 0 0 0 0 0 0 
1479.704769 0.00146621631 0.003190634646 0.003672029231 0 0 0 0 0 0 0 0 0 0 0 
1663.276205 0.003379552854 0.04643209167 0.0539399155 0 0 0 0 0 0 0 0 0 0 0 0

O comando

awk '{for(i=1;i<=NF;i++) {if($i!=0) {printf "%s ",$i > "out1"} else {printf "%s ",$i > "out2"}; if (i==NF) {printf "\n" > "out1"; printf "\n" > "out2"} }}' foo

Os arquivos de saída

cat out1

1140.271257 0.002288454025 0.002763420728 0.004142512599 
1479.704769 0.00146621631 0.003190634646 0.003672029231 
1663.276205 0.003379552854 0.04643209167 0.0539399155 

cat out2

0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0
    
por A.B. 09.09.2015 / 11:13
3

Você pode usar uma ferramenta de processamento de texto para fazer isso, mas se o objetivo é separar os 4 primeiros campos do que os segue usando cut é suficiente:

 cut -d ' ' -f 1-4 infile > outfile1
 cut -d ' ' -f 5- infile > outfile2
user@debian ~/tmp % cat infile
1140.271257 0.002288454025 0.002763420728 0.004142512599 0 0 0 0 0 0 0 0 0 0 0 
1479.704769 0.00146621631 0.003190634646 0.003672029231 0 0 0 0 0 0 0 0 0 0 0 
1663.276205 0.003379552854 0.04643209167 0.0539399155 0 0 0 0 0 0 0 0 0 0 0 0 
user@debian ~/tmp % cut -d ' ' -f 1-4 infile
1140.271257 0.002288454025 0.002763420728 0.004142512599
1479.704769 0.00146621631 0.003190634646 0.003672029231
1663.276205 0.003379552854 0.04643209167 0.0539399155
user@debian ~/tmp % cut -d ' ' -f 5- infile 
0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 
    
por kos 09.09.2015 / 11:13
2

Eu recomendaria usar o perl para isso. salve sua entrada em input.txt e execute o seguinte comando:

cat input.txt | perl -ane 'foreach(@F){   #loop through input and split each line into an array
  chomp; #remove trailing newline
  if($_ == 0){   #print the element to STDOUT if it is "0"
    print $_," "
  }
  else{     #print the element to STDERR if it is not "0"
    print STDERR $_," "
    }
  };
  print "\n"; print STDERR "\n";' #add a newline at the end 
> x2.txt 2> x1.txt    #redirect STDOUT to x2.txt and STDERR to x1.txt

aqui como um verso para copiar e colar:

cat input.txt | perl -ane 'foreach(@F){chomp;if($_ == 0){print $_," "}else{print STDERR $_," "}};print "\n"; print STDERR "\n";' > x2.txt 2> 1.txt
    
por Wayne_Yux 09.09.2015 / 11:10
2
  

Basta pegar os primeiros números, que não são 0, e depois colocar o   descansar em outro arquivo

Nesse caso, você pode usar grep com Regex compatível com Perl ( -P ):

  • Para obter os primeiros números que não são zero:

    $ grep -Po '^.*\s\d+\.\d+(?=\s0\s.*)' file.txt 
    1140.271257 0.002288454025 0.002763420728 0.004142512599
    1479.704769 0.00146621631 0.003190634646 0.003672029231
    1663.276205 0.003379552854 0.04643209167 0.0539399155
    
    • ^.*\s\d+\.\d+ receberá nossa parte desejada

    • (?=\s0\s.*) é um padrão de lookahead positivo de largura zero garantindo que tenhamos o início de zeros após nossa posição desejada

    Para salvá-lo como filex1.txt :

    grep -Po '^.*\s\d+\.\d+(?=\s0\s.*)' file.txt >filex1.txt
    
  • Para obter o restante, ou seja, zeros:

    $ grep -Po '\s\d+\.\d+\s\K0\s.*' file.txt 
    0 0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 0 0
    
    • \s\d+\.\d+\s garantirá que tenhamos uma entrada diferente de zero antes da parte desejada, \K descartará a correspondência

    • 0\s.* nos dará a parte desejada, ou seja, zero entradas a partir do primeiro

    Para salvá-lo como filex2.txt :

    grep -Po '\s\d+\.\d+\s\K0\s.*' file.txt >filex2.txt
    
por heemayl 09.09.2015 / 11:58
2

Outra abordagem usando o Perl:

perl -lne '/(.*?)\s(0\s.*)/; print ""; print STDERR ""' file > filex1 2> filex2

A expressão regular corresponderá a todos os itens até o primeiro 0 cercado por espaço em branco e, em seguida, tudo, desde 0 até o final da linha. Os parênteses capturam esses dois grupos como e , respectivamente. O -l ativa a remoção automática de nova linha à direita ( chomp ) e adiciona \n a cada print de chamada. Portanto, imprimimos para a saída padrão e para o erro padrão e, em seguida, redirecionamos cada um para um arquivo diferente.

Como isso é Perl, há mais de uma maneira de fazer isso. Esta é a mesma ideia que a resposta de Wayne_Yux, mas simplificada:

perl -lane '@A=grep{$_==0}@F; @B=grep{$_!=0}@F;print STDERR "@A"; print "@B"' file > filex1 2>filex2

Alternativamente, um grep -P :

mais simples
grep -oP '^.+?(?=\s0\s)' file > filex1
grep -oP ' \K0 .*' file > filex2
    
por terdon 09.09.2015 / 13:37
0

Supondo que uma vez que você tenha um 0 , todos os outros campos são assim, você pode dizer:

awk -v FS=" 0 " '{print  > "f1"; gsub( " ",""); print > "f2"}' file

Isso define o separador de campo como a string 0 e imprime o primeiro campo (ou seja, até o primeiro 0 ) no arquivo f1 . Em seguida, remove este primeiro campo da linha original e imprime seu resultado no arquivo f2 .

    
por fedorqui 09.09.2015 / 15:07