web-dev-qa-db-fra.com

Comment grep deux nombres de la même ligne à différents endroits en utilisant bash?

Je veux grep 2 nombres de la même ligne dans l'exemple ci-dessous:

// 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

J'ai besoin du numéro à droite de "résolver.cpp: 229] Itération" et à droite de ", perte =". Je dois obtenir les deux nombres en même temps, de sorte que mon fichier résultant ressemble à ceci:

// ResultFile.txt
2000 0.305721
2020 0.294722

Je sais seulement comment obtenir un des nombres en utilisant grep comme ceci

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

Est-ce que quelqu'un sait comment obtenir le deuxième numéro simultanément?

6
mcExchange

Une façon possible ...

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

J'ai perdu grep mais ici c'est avec sed

$ sed -nr 's/.*Iteration ([0-9]+).*loss.*( [0-9]+.*)/\1\2/p' ExampleFile.txt
2000 0.305721
2020 0.294722
  • -n n'imprimez pas avant d'avoir demandé quelque chose
  • -r utilise ERE afin que je n'ai pas à échapper aux métacaractères () et +
  • s rechercher et remplacer /old/new/
  • .* correspond à tout (ou à aucun) caractère
  • ([0-9]+) parenthèses pour conserver cette partie du motif [0-9] un nombre + une ou plusieurs occurrences du caractère précédent.
  • \1\2 références arrière aux modèles enregistrés précédemment avec des parenthèses
  • p imprimer les bits que nous voulons voir

Si le résultat est ce que vous voulez, redirigez-le vers votre fichier:

sed -nr 's/.*Iteration ([0-9]+).*loss.*( [0-9]+.*)/\1\2/p' ExampleFile.txt > ResultFile.txt
7
Zanna

Avec awk, spécifiez F ield separator comme ',' virgule et 'espace' et faites correspondre les lignes contenant "Itération" dans, puis affichez les colonnes # 3 et # 7 (ou $ NF en tant que dernière). colonne au lieu de 7 $)

awk -F'[, ]' '/Iteration/ {print $3,$7}' infile
5
αғsнιη
Perl -nE '/\].*?(\d+),.*loss = (\d+\.\d+)/ and say "$1 $2"' infile
  • if (line correspond à l'expression régulière), affiche les groupes appropriés.
1
user216043