Comment puis-je faire sed
des lignes de filtrage correspondant à une expression, mais ignorer les lignes non correspondantes, au lieu de les laisser s'imprimer?
À titre d'exemple réel, je veux exécuter scalac
(le compilateur Scala) sur un ensemble de fichiers et lire à partir de sa -verbose
sortie les .class
fichiers créés. scalac -verbose
renvoie un tas de messages, mais nous ne sommes intéressés que par ceux du formulaire [wrote some-class-name.class]
. Ce que je fais actuellement est la suivante ( |&
est la manière de bash 4.0 de 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 laissera également passer tous les autres messages inchangés! Bien sûr, nous pourrions faire à la place 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
à ignorer les lignes non correspondantes de l'entrée. Alors, comment faisons-nous cela?
Réponses:
Une autre façon avec le sed plain:
s///
est une substitution,t
sans aucune étiquette saute conditionnellement toutes les commandes suivantes,d
supprime la ligne.Pas besoin de perl ou de grep.
(édité après la suggestion de Nicholas Riley)
la source
tx
etd
avec une nouvelle ligne plutôt qu'un point-virgule comme j'obtenaisundefined label 'x;d;:x'
.sed -e 's/.../.../' -e 'tx' -e 'd' -e ':x'
(suggéré dans un commentaire sur une question similaire ).sed -e 's/.../.../' -e 't' -e 'd'
.-e
option, alors ne le mentionnez pas en général.Si vous ne souhaitez pas imprimer des lignes qui ne correspondent pas, vous pouvez utiliser la combinaison de
-n
option qui dit à sed de ne pas imprimerp
indicateur qui indique à sed d'afficher ce qui correspondCela donne:
la source
echo foo | sed -n -e 's/foo/bar/p' -e 's/bar/oof/p'
affichera les deuxbar
etoof
sur des lignes séparées. Bien que la variété goto-label ne puisse pas non plus gérer plusieurs modèles puisqu'elle supprimera la ligne si le premier modèle ne correspond pas.Utilisez Perl:
la source
Il n'y a pas besoin de substitution.
la source
Rapsey a soulevé un point pertinent concernant les expressions de substitutions multiples.
{}
(séparées par un point-virgule;
ou une nouvelle ligne)Syntaxe:
Exemple (voir le document Here pour plus de détails):
Code:
Résultat:
la source