Como grep linhas que possuem determinado valor em uma coluna específica?

6

Eu tenho um arquivo como o seguinte

  200.000    1.353    0.086
  200.250    1.417    0.000
  200.500    1.359    0.091
  200.750    1.423    0.000
  201.000    1.365    0.093
  201.250    1.427    0.000
  201.500    1.373    0.093
  201.750    1.432    0.000
  202.000    1.383    0.091
  202.250    1.435    0.000
  202.500    1.392    0.087
  202.750    1.436    0.000
  203.000    1.402    0.081
  203.250    1.437    0.001
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045  

Eu gostaria de grep apenas as linhas que têm na primeira coluna o decimal 0,000 e 0,500 só assim a saída seria assim

  200.000    1.353    0.086
  200.500    1.359    0.091
  201.000    1.365    0.093
  201.500    1.373    0.093
  202.000    1.383    0.091
  202.500    1.392    0.087
  203.000    1.402    0.081
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045  
    
por Mohsen El-Tahawy 31.10.2016 / 22:13

8 respostas

10

Você não usa grep. Use awk .

"your data" | awk '$1 ~ /\.[05]00/'
    
por 31.10.2016 / 22:54
4

I would like to grep only the rows that have in the first column the decimal .000 and .500

Meu primeiro pensamento

grep '^ *[0-9][0-9][0-9]\.[50]00' filename

Teste rápido usando o WSL

$ head testdata
              200.000    1.353    0.086
              200.250    1.417    0.000
              200.500    1.359    0.091
              200.750    1.423    0.000
              201.000    1.365    0.093
              201.250    1.427    0.000
              201.500    1.373    0.093
              201.750    1.432    0.000
              202.000    1.383    0.091
              202.250    1.435    0.000
$ grep '^ *[0-9][0-9][0-9]\.[50]00' testdata
              200.000    1.353    0.086
              200.500    1.359    0.091
              201.000    1.365    0.093
              201.500    1.373    0.093
              202.000    1.383    0.091
              202.500    1.392    0.087
              203.000    1.402    0.081
              203.500    1.412    0.073
              204.000    1.423    0.065
              204.500    1.432    0.055
              205.000    1.441    0.045

Existem maneiras mais concisas de expressar isso.

$ grep -E '^ *[0-9]{3}\.[50]00' testdata
              200.000    1.353    0.086
              200.500    1.359    0.091
              201.000    1.365    0.093
              201.500    1.373    0.093
              202.000    1.383    0.091
              202.500    1.392    0.087
              203.000    1.402    0.081
              203.500    1.412    0.073
              204.000    1.423    0.065
              204.500    1.432    0.055
              205.000    1.441    0.045

Se a primeira coluna pode ter uma parte inteira diferente de 3 dígitos

grep -E '^ *[0-9]+\.[05]00' testdata

Em algumas circunstâncias, talvez seja necessário usar [:digit:] no lugar de [0-9] .

E assim por diante.

man grep é seu amigo.

    
por 01.11.2016 / 01:29
3
awk '$1 ~ /\.[50]00/ { print $0 }' myFile.txt

A primeira coluna $1 será correspondida em relação a /\.500|\.000/ , os pontos são escapados para serem pontos literais, não regexem qualquer caractere que a ~ corresponde parcialmente e imprime a linha inteira $0

    
por 31.10.2016 / 22:57
2

Dependendo do seu caso de uso, você também pode usar operações numéricas reais:

$ awk '{a = $1 % 1} a == 0 || a == 0.5' /tmp/foo
  200.000    1.353    0.086
  200.500    1.359    0.091
  201.000    1.365    0.093
  201.500    1.373    0.093
  202.000    1.383    0.091
  202.500    1.392    0.087
  203.000    1.402    0.081
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045

Testado com o BSD awk (OSX El Capitan, 20070501) e o GNU awk 4.1.4.

    
por 01.11.2016 / 03:21
2
 grep -e '2[^ ]*.000' -e '2[^ ]*.500' file.txt
    
por 01.11.2016 / 09:25
2

com awk :

$>awk '$1%.5==0' data.tsv 
200.000 1.353   0.086
200.500 1.359   0.091
201.000 1.365   0.093
201.500 1.373   0.093
202.000 1.383   0.091
202.500 1.392   0.087
203.000 1.402   0.081
203.500 1.412   0.073
204.000 1.423   0.065
204.500 1.432   0.055
205.000 1.441   0.045

Com mlr :

$>mlr --ifs tab --onidx filter '$1%.5==0' data.tsv 
200.000 1.353 0.086
200.500 1.359 0.091
201.000 1.365 0.093
201.500 1.373 0.093
202.000 1.383 0.091
202.500 1.392 0.087
203.000 1.402 0.081
203.500 1.412 0.073
204.000 1.423 0.065
204.500 1.432 0.055
205.000 1.441 0.045
    
por 01.11.2016 / 09:55
2

Ok, um pouco tarde adicionando minha contribuição, mas acho que vale a pena.

O requisito a cumprir, por OP, é a primeira coluna com o valor decimal de .000 ou .500 apenas. Não há estipulação quanto ao valor inicial, seja por intervalo ou comprimento. Para robustez, não se deve presumir que seja restrito a nada, exceto que não há caracteres não-brancos antes da primeira coluna (ou não é mais a primeira coluna) e que o conteúdo da primeira coluna será tem um ponto decimal, . , em algum lugar.

O OP está querendo usar grep , que irá imprimir toda a linha quando uma correspondência for encontrada, então a única coisa a fazer é criar o padrão que corresponde a todos e somente o que é necessário.

A simplicidade em si e nenhuma razão para usar sed ou awk como 'grep pode manipular a origem como um arquivo ou um canal.

Para grep um arquivo use grep '^[^.]*\.[05]0\{2\}\s' the_file.txt

Para grep de um canal, use my_command | grep '^[^.]*\.[05]0\{2\}\s'

O padrão é: ^ , começa no início da linha; [^.] , corresponde a qualquer caractere não decimal; * , tantas vezes quanto possível (incluindo nenhuma); \. , corresponde a um ponto decimal; [05] , corresponde a cinco ou a zero; 0\{2\} , corresponde a mais dois zeros (as barras invertidas antes da chave de abertura e fechamento impedem que o shell tente fazer a expansão de contraventamento); \s , corresponde a um caractere de espaço em branco (significando o final da coluna - para usar em um caso de uso diferente, substitua pelo separador de coluna, normalmente um comman, um ponto e vírgula ou uma tabulação \t ).

Observe que isso corresponderá exatamente ao que o OP fez. Ele não corresponderá a .5000 ou .0000 , embora seja numericamente equivalente, porque o padrão procura cinco ou um zero, seguido por exatamente 2 mais zeros seguidos por espaço em branco . Se isso for significativo, todas as outras respostas, até o momento, falharão, pois corresponderão a qualquer número de zeros, maior que 1, após o dígito do teste. E exceto pela resposta de FloHimself, eles corresponderão a qualquer coisa na segunda coluna que começa .000 ou .500 , incluindo .0003 e .500T , e aquele por FloHimself corresponderá a qualquer coisa que seja matematicamente equivalente a .0 e .5 , não importa quantos zeros existam. O último, embora não seja compatível com o que o OP declarou, provavelmente corresponderá ao que o OP precisa de qualquer maneira.

Finalmente, se a potência e a velocidade de awk forem desejadas, mesmo que o OP tenha solicitado grep , o comando seria:

Com um arquivo awk '$1 ~ /[^.]\.[05]0{2}$/' the_file.txt

Com um pipe my_command | awk '$1 ~ /[^.]\.[05]0{2}$/'

    
por 23.04.2017 / 09:52
1

Se você insistir em usar o grep, isso pode funcionar para você. Salvei a primeira saída que você fornece em um arquivo de texto chamado "file.txt" e usei o seguinte comando:

grep -e '2[^ ]*.000' file.txt & grep -e '2[^ ]*.500' file.txt

O que dá uma saída de:

200.000    1.353    0.086
200.500    1.359    0.091
201.500    1.373    0.093
201.000    1.365    0.093
202.500    1.392    0.087
202.000    1.383    0.091
203.500    1.412    0.073
203.000    1.402    0.081
204.500    1.432    0.055
204.000    1.423    0.065
205.000    1.441    0.045

Você não precisará salvar a saída em um arquivo de texto se já estiver em um arquivo. Mas caso não esteja sendo salvo em um arquivo, você também pode enviar os dados para o comando grep que eu forneci e ele deve funcionar pelo menos até que o primeiro número, 2 , na primeira coluna, não seja mais um 2 . Nesse ponto, você precisará atualizar o comando grep com o caractere apropriado para imprimir corretamente.

O que está acontecendo com esse comando grep é que o primeiro grep está sendo enviado para o segundo plano com o operador & . Como ele é enviado para o segundo plano, o próximo comando grep é executado imediatamente depois, fornecendo uma saída uniforme. Para que a tarefa que você precisa concluir seja feita mais facilmente, você deve seguir o exemplo que outros forneceram e usar awk ou mesmo sed .

(editar)

Este não é o uso melhor ou mais eficaz do grep para as suas necessidades, mas deve ser suficiente para você brincar um pouco e ter uma idéia melhor do grep.

    
por 01.11.2016 / 09:18

Tags