Comment puis-je faire sed
filtrer les lignes correspondantes selon une expression, mais ignorer les lignes qui ne correspondent pas, au lieu de les laisser imprimer?
Par exemple, je veux exécuter scalac
(le compilateur Scala) sur un ensemble de fichiers et lire à partir de son -verbose
afficher le .class
fichiers créés. scalac -verbose
affiche un tas de messages, mais nous ne sommes intéressés que par ceux de la forme [wrote some-class-name.class]
. Voici ce que je fais actuellement (|&
est le moyen de bash 4.0 pour diriger stderr vers le programme suivant):
$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/'
Cela extraira les noms de fichiers des messages qui nous intéressent, mais permettra également à tous les autres messages de passer inchangés! Bien sûr, nous pourrions faire ceci:
$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' |
sed 's/^\[wrote \(.*\.class\)\]$/\1/'
qui fonctionne mais ressemble beaucoup à contourner le vrai problème, qui est de savoir comment demander à sed
d'ignorer les lignes non correspondantes de l'entrée. Alors, comment on fait ça?
Une autre façon avec plain sed:
sed -e 's/.../.../;t;d'
s///
est une substitution, t
sans aucune étiquette ignore conditionnellement toutes les commandes suivantes, d
supprime la ligne.
Pas besoin de Perl ou grep.
(édité après la suggestion de Nicholas Riley)
Si vous ne souhaitez pas imprimer des lignes qui ne correspondent pas, vous pouvez utiliser la combinaison de
-n
option qui indique à sed de ne pas imprimerp
drapeau qui indique à sed d'imprimer ce qui correspondCela donne:
sed -n 's/.../.../p'
Utilisez Perl:
... |& Perl -ne 'print "$1\n" if /^\[wrote (.*\.class)\]$/'