web-dev-qa-db-fra.com

Comment imprimer un motif de regex assorti avec awk?

En utilisant awk, je dois trouver un mot dans un fichier qui correspond à un motif de regex.

Je seulement souhaite imprimer le mot correspondant au motif.

Donc si dans la ligne, j'ai:

xxx yyy zzz

Et motif:

/yyy/

Je veux seulement obtenir:

yyy

EDIT: grâce à kurumi j’ai réussi à écrire quelque chose comme ceci:

awk '{
        for(i=1; i<=NF; i++) {
                tmp=match($i, /[0-9]..?.?[^A-Za-z0-9]/)
                if(tmp) {
                        print $i
                }
        }
}' $1

et c'est ce dont j'avais besoin :) merci beaucoup!

89
marverix

C'est le très basique

awk '/pattern/{ print $0 }' file

demandez à awk de rechercher pattern à l'aide de //, puis imprimez la ligne qui est appelée par défaut un enregistrement, noté $ 0. Au moins, lisez le documentation .

Si vous voulez seulement imprimer le mot correspondant.

awk '{for(i=1;i<=NF;i++){ if($i=="yyy"){print $i} } }' file
130
kurumi

On dirait que vous essayez d'imiter le comportement de grep -o de GNU. Cela fera que si vous voulez seulement la première correspondance sur chaque ligne:

awk 'match($0, /regex/) {
    print substr($0, RSTART, RLENGTH)
}
' file

Voici un exemple:

% awk 'match($0, /a.t/) {
    print substr($0, RSTART, RLENGTH)
}
' /usr/share/dict/words | head
act
act
act
act
aft
ant
apt
art
art
art

Lisez à propos de match , substr , RSTART et RLENGTH dans le manuel awk.

Après cela, vous voudrez peut-être étendre ceci pour traiter plusieurs correspondances sur la même ligne. Je ne peux pas tous faire vos devoirs pour vous :-)

100
Johnsyweb

gawk peut obtenir la partie correspondante de chaque ligne en utilisant ceci comme action:

{ if (match($0,/your regexp/,m)) print m[0] }

match (string, regexp [ array]) Si array est présent, il est effacé, puis l'élément zeroth de array est défini sur la portion entière de la chaîne correspondant à regexp. Si regexp contient des parenthèses, les éléments de tableau indexés en nombres entiers sont définis pour contenir la portion de chaîne correspondant à la sous-expression entre parenthèses correspondante. http://www.gnu.org/software/gawk/manual/gawk.html#String-Functions

29
royas

Si vous ne vous intéressez qu'à la dernière ligne d'entrée et que vous vous attendez à ne trouver qu'une seule correspondance (par exemple, une partie de la ligne de résumé d'une commande Shell), vous pouvez également essayer ce code très compact, adopté depuis Comment imprimer les correspondances regexp en utilisant `awk`? :

$ echo "xxx yyy zzz" | awk '{match($0,"yyy",a)}END{print a[0]}'
yyy

Ou la version plus complexe avec un résultat partiel:

$ echo "xxx=a yyy=b zzz=c" | awk '{match($0,"yyy=([^ ]+)",a)}END{print a[1]}'
b

Attention: la fonction awkmatch() à trois arguments n'existe que dans gawk, pas dans mawk

Voici une autre solution intéressante utilisant un recherche derrière une expression rationnelle dans grep au lieu de awk. Cette solution a des exigences moindres pour votre installation:

$ echo "xxx=a yyy=b zzz=c" | grep -Po '(?<=yyy=)[^ ]+'
b
9
Daniel Alder

Si Perl est une option, vous pouvez essayer ceci:

Perl -lne 'print $1 if /(regex)/' file

Pour implémenter la correspondance sans distinction de casse, ajoutez le modificateur i.

Perl -lne 'print $1 if /(regex)/i' file

Pour tout imprimer APRES le match:

Perl -lne 'if ($found){print} else{if (/regex(.*)/){print $1; $found++}}' textfile

Pour imprimer le match et le reste après le match:

Perl -lne 'if ($found){print} else{if (/(regex.*)/){print $1; $found++}}' textfile
9
Chris Koknat

L'utilisation de sed peut également être élégante dans cette situation. Exemple (remplacez la ligne par le groupe correspondant "yyy" de la ligne):

$ cat testfile
xxx yyy zzz
yyy xxx zzz
$ cat testfile | sed -r 's#^.*(yyy).*$#\1#g'
yyy
yyy

Page de manuel pertinente: https://www.gnu.org/software/sed/manual/sed.html#Back_002dreferences-and-Subexpressions

2
Konrad Brodzik