100 votes

comment utiliser sed, awk ou gawk pour n'imprimer que ce qui correspond?

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 de rester bouche bée.

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 d'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 )

Les choses que j'ai essayé de comprendre:

sed -e 's/.*([0-9]).*/\\1/g' example.txt # extracts the entire input file
sed -n 's/.*([0-9]).*/\\1/g' example.txt # extracts nothing

42voto

mouviciel Points 36624

Mon sed (Mac OS X) ne fonctionnait pas avec + . J'ai essayé * place et j'ai ajouté les balises p pour l'impression du match:

 sed -n 's/^.*abc\([0-9]*\)xyz.*$/\1/p' example.txt
 

Pour faire correspondre au moins un caractère numérique sans + , j'utiliserais:

 sed -n 's/^.*abc\([0-9][0-9]*\)xyz.*$/\1/p' example.txt
 

17voto

PP. Points 6741

J'utilise perl pour rendre cela plus facile pour moi. par exemple

perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/'

Cela va à l'Perl, l' -n option indique à Perl de la lecture dans une ligne à la fois à partir de STDIN et exécuter le code. L' -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

5voto

Jim Dennis Points 5454

Si votre version de grep prend en charge vous pouvez utiliser l' -o option pour imprimer uniquement la partie de la ligne qui correspond à votre regexp.

Si non, alors voici les meilleures sed que je pouvais venir avec:

sed -e '/[0-9]/!d' -e 's/^[^0-9]*//' -e 's/[^0-9]*$//'

... 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:

sed -e 's/.*\([0-9]*\).*/&/'

.... ou

sed -e 's/.*\([0-9]*\).*/\1/'

... est - sed prend uniquement en charge les "gourmands" ... 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 d' sed 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).

2voto

Mark Lakata Points 3458

perl est la syntaxe la plus propre, mais si vous n'avez pas perl (pas toujours là, je comprends), la seule façon d'utiliser gawk et les composants d'une expression régulière est d'utiliser la fonction gensub.

 gawk '/abc[0-9]+xyz/ { print gensub(/.*([0-9]+).*/,"\\1","g"); } < file
 

la sortie de l'exemple de fichier d'entrée sera

 12345
 

Remarque: gensub remplace l'intégralité de la regex entière (entre les //), vous devez donc placer le. * Avant et après le ([0-9] +) pour supprimer le texte avant et après le nombre indiqué dans la substitution.

1voto

paxdiablo Points 341644

Si vous souhaitez sélectionner des lignes, puis d'en extraire les bits que vous ne voulez pas que:

egrep 'abc[0-9]+xyz' inputFile | sed -e 's/^.*abc//' -e 's/xyz.*$//'

Essentiellement, il sélectionne les lignes que vous voulez avec egrep , puis utilise sed de dépouiller les bits d'avant et d'après le nombre.

Vous pouvez le voir en action ici:

pax> echo 'a
b
c
abc12345xyz
a
b
c' | egrep 'abc[0-9]+xyz' | sed -e 's/^.*abc//' -e 's/xyz.*$//'
12345
pax> 

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:

egrep '[^0-9]*[0-9]+[^0-9]*$' inputFile | sed -e 's/^[^0-9]*//' -e 's/[^0-9]*$//'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X