Como grep dois números da mesma linha em lugares diferentes usando o bash?

7

Eu quero grep 2 números da mesma linha no exemplo abaixo:

// ExampleFile.txt
solver.cpp:229] Iteration 2000, loss = 0.305721
solver.cpp:245]     Train net output #0: accuracy = 0.926112
solver.cpp:245]     Train net output #1: accuracy = 0.723957
solver.cpp:245]     Train net output #2: accuracy = 0.599623
sgd_solver.cpp:106] Iteration 2000, lr = 0.000227383
solver.cpp:229] Iteration 2020, loss = 0.294722
solver.cpp:245]     Train net output #0: accuracy = 0.855208
solver.cpp:245]     Train net output #1: accuracy = 0.71616
solver.cpp:245]     Train net output #2: accuracy = 0.619429

Eu preciso do número à direita de "solver.cpp: 229] Iteração" e à direita de ", perda=". Preciso obter os dois números ao mesmo tempo, de modo que o arquivo resultante seja assim:

// ResultFile.txt
2000 0.305721
2020 0.294722

Eu só sei como obter um dos números usando grep como este

grep ", loss = " ExampleFile.txt | sed -e "s/.* //" > ResultFile.txt

Alguém sabe como obter o segundo número simultaneamente?

    
por mcExchange 08.11.2016 / 11:01

4 respostas

8

Uma maneira possível ...

% grep 'solver.cpp:229' ExampleFile.txt | cut -d ' ' -f 3,6 | tr -d ','
2000 0.305721
2020 0.294722
    
por fkraiem 08.11.2016 / 11:11
8

Eu perdi grep , mas aqui está com sed

$ sed -nr 's/.*Iteration ([0-9]+).*loss.*( [0-9]+.*)//p' ExampleFile.txt
2000 0.305721
2020 0.294722
  • -n não imprime até pedirmos algo
  • -r usa o ERE, portanto, não preciso escapar dos () e + metacaracteres
  • s procura e substitui /old/new/
  • .* corresponde a qualquer (ou nenhum) caractere
  • ([0-9]+) parênteses para manter essa parte do padrão [0-9] um número + uma ou mais ocorrências do caractere anterior.
  • faz referência aos padrões salvos anteriormente com parênteses
  • p imprime os bits que queremos ver

Se a saída é o que você quer, redirecione-a para o seu outfile:

sed -nr 's/.*Iteration ([0-9]+).*loss.*( [0-9]+.*)//p' ExampleFile.txt > ResultFile.txt
    
por Zanna 08.11.2016 / 11:19
5

Com awk, especifique F separador ield como ',' vírgula e 'espaço' e corresponda às linhas que contenham "Iteração", depois imprima as colunas # 3 e # 7 (ou $ NF como última coluna em vez de $ 7)

awk -F'[, ]' '/Iteration/ {print ,}' infile
    
por αғsнιη 08.11.2016 / 12:10
1
perl -nE '/\].*?(\d+),.*loss = (\d+\.\d+)/ and say " "' infile
  • se (a linha corresponder à expressão regular), imprima os grupos relevantes.
por JJoao 08.11.2016 / 17:16