2009-11-20 3 views
8

je vis deComment utiliser sed pour renvoyer quelque chose de la première ligne qui correspond et quitte tôt?

How to use sed to replace only the first occurrence in a file?

Comment faire plus de ce que je veux:

sed -n '0,/.*\(something\).*/s//\1/p' 

ce trouve le premier match de quelque chose et il extrait (bien sûr, mon exemple réel est plus complexe) . Je sais que sed a une commande 'quit' qui le fera s'arrêter tôt, mais je ne sais pas comment combiner le 'q' avec la ligne ci-dessus pour obtenir le comportement désiré.

J'ai essayé de remplacer le 'p' par {p; q;} comme je l'ai vu dans certains exemples, mais cela ne marche clairement pas.

+0

Pouvez-vous montrer plus de ce que vous obtenez et ce que vous voulez et comment ils diffèrent? J'ai fait 'echo -e" aaa 111 aaa \ nbbb 111 bbb "| sed -n '0, /. * \ (111 \). */S // \ 1/p'' et j'ai obtenu un" 111 ". Ensuite, j'ai fait 'echo -e" aaa 111 aaa \ nbbb 111 bbb "| sed -n '0,/\ (. * \ (111 \). * \)/S // \ 1/p'' pour montrer le ligne complète pour s'assurer de ce qu'il obtenait et il sort "aaa 111 aaa" qui est ce que je m'attendais. Notez que je n'utilise pas de 'q'. Comment ça "ne fonctionne pas" pour vous. –

+0

Votre méthode génère la sortie correcte, mais elle continue à traiter le fichier entier même s'il n'y a plus de travail à faire, ce qui est horrible pour les fichiers géants ou lorsqu'ils sont utilisés dans un pipeline.Mon cas d'utilisation spécifique était de trouver via 'git log' sur un arbre importé git-p4 qui utilisait la branche perforce pour le dernier commit. git log (quand il est appelé sans -n enregistrera tous les commit qui se sont produits (des centaines de milliers pour moi) Nous ne pouvons pas savoir a priori quelle valeur donner à git pour '-n.' Ma solution était: git log | sed -n '0, /. * \ [git-p4:. * \/\/dépôt \/blah \/\ ([^ \ /] * \) \ /.*/ s // \ 1/p;/\ [git-p4/q ' – nosatalian

Répondre

3

Mon cas précis d'utilisation était de trouver via « git log » sur un arbre importé git-p4 qui branche a été utilisée forcément se pour la dernière validation. git log (quand il est appelé sans -n consignera toutes les validations qui ont eu lieu (des centaines de milliers pour moi)).

Nous ne pouvons pas savoir a priori quelle valeur donner à git pour '-n.' Après avoir affiché ce, j'ai trouvé ma solution était:

git log | sed -n '0,/.*\[git-p4:.*\/\/depot\/blah\/\([^\/]*\)\/.*/s//\1/p; /\[git-p4/ q' 

Je voudrais encore savoir comment faire cela avec un séparateur non «/», et sans avoir à spécifier la partie « git-p4 » deux fois , une fois pour l'extraction et une fois pour l'abandon. Il doit y avoir un moyen de combiner les deux sur la même ligne ...

1

Sed a généralement une option pour spécifier plus d'un modèle à exécuter (IIRC, c'est l'option -e). De cette façon, vous pouvez spécifier un deuxième motif qui se ferme après la première ligne.

Une autre approche consiste à utiliser sed pour extraire la première ligne (sed '1q'), puis de la rediriger vers une deuxième commande sed (ce que vous montrez ci-dessus).

1

utilisation gawk

gawk '/MATCH/{ 
      print "do something with "$0 
      exit 
}' file 
9

L'astuce "print and quit" fonctionne, si vous mettez aussi la commande de substitution dans le bloc (au lieu de mettre seulement l'impression et de quitter).

Essayez:

sed -n '/.*\(something\).*/{s//\1/p;q}' 

Lire cela comme: Match pour le motif donné entre les barres obliques. Si ce motif est trouvé, exécutez les actions spécifiées dans le bloc: Remplacer, imprimer et quitter. En règle générale, les modèles de correspondance et de substitution sont égaux, mais cela n'est pas obligatoire, de sorte que la commande 's' peut également contenir un objet RE différent.

En fait, c'est assez similaire à ce que ghostdog74 a répondu pour gawk.

+0

OpenBSD nécessite un point-virgule après la commande quit ('q'). –

Questions connexes