comment utiliser sed, awk, ou gawk pour n'imprimer que ce qui est en correspondance?
Je vois beaucoup d'exemples et de pages de manuel sur la façon de faire les choses comme pour la recherche et les remplacer à l'aide de sed, awk, ou gawk.
Mais dans mon cas, j'ai une expression régulière qui je veux courir à l'encontre d'un fichier texte pour en extraire une valeur spécifique. Je ne veux pas faire de recherche et remplacement. C'est être appelé à partir de bash. Prenons un exemple:
Exemple de l'expression régulière:
.*abc([0-9]+)xyz.*
Exemple de fichier d'entrée:
a
b
c
abc12345xyz
a
b
c
Aussi simple que cela puisse paraître, je ne peux pas comprendre comment appeler sed/awk/gawk correctement. Ce que j'espérais faire, c'est de l'intérieur de mon script bash ont:
myvalue=$( sed <...something...> input.txt )
Choses que j'ai essayé de comprendre:
sed -e 's/.*([0-9]).*/\/g' example.txt # extracts the entire input file
sed -n 's/.*([0-9]).*/\/g' example.txt # extracts nothing
- Wow...les gens ont voté cette question en baisse de -1? Est-ce vraiment inapproprié d'une question?
- Il semble tout à fait approprié, en utilisant les Regex et puissants utilitaires de ligne de commande comme sed/awk ou tout éditeur de texte comme vi, emacs ou teco peut être plus comme de la programmation que de simplement en utilisant certains ol' application. IMO ça, c'est TELLEMENT plus que SU.
- Peut-être qu'il a été rejeté parce que, dans sa forme initiale, il n'a pas de définir clairement certaines de ses exigences. Ça ne fonctionne toujours pas, sauf si vous lisez l'OP commentaires aux réponses (y compris celui que j'ai supprimé quand les choses sont allées en forme de poire).
Vous devez vous connecter pour publier un commentaire.
Mon
sed
(Mac OS X) ne fonctionne pas avec+
. J'ai essayé*
à la place et j'ai ajoutép
balise pour l'impression match:Pour la mise en correspondance d'au moins un caractère numérique sans
+
, je voudrais utiliser:+
et puis il a travaillé pour moi:sed -n 's/^.*abc\([0-9]\+\)xyz.*$/\1/p'
Vous pouvez utiliser sed pour ce faire
-n
ne pas imprimer de la ligne-r
ce qui le rend si vous n'avez pas échapper à la capture du groupe parens()
.\1
la capture match du groupe/g
mondial de match/p
imprimer le résultatJ'ai écrit un outil pour moi-même qui rend cela plus facile
- Je utiliser
perl
pour rendre cela plus facile pour moi. par exemple,Cela va à Perl, le
-n
option indique à Perl de la lecture dans une ligne à la fois à partir de STDIN et exécuter le code. Le-e
option spécifie l'instruction à exécuter.L'instruction exécute une regexp sur la ligne de lire, et si elle correspond imprime le contenu de la première série de bracks (
$1
).Vous pouvez faire cela de multiples noms de fichier sur la fin aussi. par exemple,
perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/' example1.txt example2.txt
Si votre version de
grep
prend en charge, vous pouvez utiliser les-o
option pour imprimer seulement la partie de la ligne qui correspond à votre regexp.Si non, alors voici la meilleure
sed
que je pouvais venir:... qui supprime/saute sans chiffres et, pour les autres lignes, supprime toutes les attaque et de fuite des non-caractères numériques. (Je suis seulement deviner que votre intention est d'extraire le numéro de chaque ligne qui contient un).
Le problème avec quelque chose comme:
.... ou
... est-ce que
sed
prend uniquement en charge les "gourmands" match ... de sorte que la première .* correspondra le reste de la ligne. Sauf si nous pouvons utiliser une niée classe de personnage pour obtenir un non-gourmand match ... ou une version desed
avec Perl-compatible ou d'autres extensions de ses regexes, nous ne pouvons pas extraire un motif précis match de avec le modèle de l'espace (d'une ligne).sed
commandes de cette manière:sed -n 's/[^0-9]*\([0-9]\+\).*/\1/p'
grep -o
! J'ai essayé de le faire avecsed
et a lutté avec mon besoin de trouver des correspondances multiples sur certaines lignes. Ma solution est stackoverflow.com/a/58308239/117471Vous pouvez utiliser
awk
avecmatch()
pour accéder à la phase de groupe:Cette tente de faire correspondre le modèle
abc[0-9]+xyz
. Si elle le fait, elle stocke ses tranches dans le tableaumatches
, dont le premier élément est le bloc[0-9]+
. Depuismatch()
renvoie la position de caractère, ou d'un index, d'où la sous-chaîne commence, paragraphe 1, si elle commence au début de la chaîne), il déclenche laprint
action.Avec
grep
vous pouvez utiliser un coup d'oeil derrière et look-ahead:Ce vérifie le motif
[0-9]+
quand il se produit au sein deabc
etxyz
et imprime juste les chiffres.perl est la plus propre syntaxe, mais si vous n'avez pas de perl (pas toujours là, je le comprends), alors la seule façon d'utiliser gawk et les composantes d'une regex est d'utiliser le gensub fonctionnalité.
sortie de l'exemple de fichier d'entrée doit être
Remarque: gensub remplace la totalité de la regex (entre //), de sorte que vous besoin de mettre de l' .* avant et après l' ([0-9]+) pour se débarrasser de texte avant et après le nombre dans la substitution.
match()
pour accéder à la phase de groupes. Voir ma réponse pour cette.Si vous souhaitez sélectionner des lignes, puis d'en extraire les bits que vous ne voulez pas:
Essentiellement, il sélectionne les lignes que vous voulez avec
egrep
et utilise ensuitesed
de dépouiller les bits avant et après la le nombre.Vous pouvez le voir en action ici:
Mise à jour: évidemment, si vous en situation réelle est plus complexe, la REs aurez besoin de moi modifiés. Par exemple, si vous avez toujours eu un seul numéro enterré à l'intérieur de zéro ou plus non-numerics au début et à la fin:
L'OP cas ne précise pas qu'il peut y avoir des correspondances multiples sur une seule ligne, mais pour le Google de la circulation, je vais ajouter un exemple pour que trop.
Depuis l'OP besoin est d'extraire d'un groupe à partir d'un modèle, à l'aide de
grep -o
nécessitera 2 passes. Mais, je trouve encore la façon la plus intuitive pour faire le travail.Depuis le temps processeur est fondamentalement libre, mais de lisibilité, est d'une valeur inestimable, j'ai tendance à refactoriser mon code basé sur la question, "un an à partir de maintenant, que vais-je pense que cela fait?" En fait, pour le code que j'ai l'intention de partager publiquement ou avec mon équipe, je vais même ouvrir
man grep
de comprendre quelle est la longue options et de remplacer ceux-ci. Comme:grep --only-matching --extended-regexp
vous pouvez le faire avec le shell
Pour awk. Je voudrais utiliser le script suivant:
([0-9+])
, ce sorties de l'ensemble de la ligne.