Si j'ai une commande awk
pattern { ... }
et pattern utilise un groupe de capture, comment puis-je accéder à la chaîne ainsi capturée dans le bloc?
C'était une promenade dans le passé ...
J'ai remplacé awk par Perl il y a longtemps.
Apparemment, le moteur des expressions régulières AWK ne capture pas ses groupes.
vous pourriez envisager d'utiliser quelque chose comme:
Perl -n -e'/test(\d+)/ && print $1'
l'indicateur -n force Perl à boucler chaque ligne comme le fait awk.
Avec gawk, vous pouvez utiliser la fonction match
pour capturer des groupes entre parenthèses.
gawk 'match($0, pattern, ary) {print ary[1]}'
exemple:
echo "abcdef" | gawk 'match($0, /b(.*)e/, a) {print a[1]}'
sorties cd
.
Notez l'utilisation spécifique de gawk qui implémente la fonctionnalité en question.
Pour une alternative portable, vous pouvez obtenir des résultats similaires avec match()
et substr
.
exemple:
echo "abcdef" | awk 'match($0, /b[^e]*/) {print substr($0, RSTART+1, RLENGTH-1)}'
sorties cd
.
C'est quelque chose dont j'ai besoin tout le temps, alors j'ai créé une fonction bash pour cela. C'est basé sur la réponse de Glenn Jackman.
Ajoutez ceci à votre .bash_profile etc.
function regex { gawk 'match($0,/'$1'/, ary) {print ary['${2:-'0'}']}'; }
Capturer une expression rationnelle pour chaque ligne du fichier
$ cat filename | regex '.*'
Capturer le groupe de capture du 1er regex pour chaque ligne du fichier
$ cat filename | regex '(.*)' 1
Vous pouvez utiliser GNU awk:
$ cat hta
RewriteCond %{HTTP_Host} !^www\.mysite\.net$
RewriteRule (.*) http://www.mysite.net/$1 [R=301,L]
$ gawk 'match($0, /.*(http.*?)\$/, m) { print m[1]; }' < hta
http://www.mysite.net/
Vous pouvez également simuler la capture dans Vanilla awk, sans extensions. Ce n'est pas intuitif si:
étape 1. utilisez gensub pour entourer les correspondances avec des caractères qui n'apparaissent pas dans votre chaîne. étape 2. Utilisez diviser contre le personnage. étape 3. Tous les autres éléments du tableau fractionné constituent votre groupe de capture.
$ echo 'ab cb ad' | awk '{split (gensub (/ a ./, SUBSEP "&" SUBSEP, "g", 0 $), plafond, SUBSEP); capuchon d'impression [2] "|" capuchon [4]; } ' ab | ad
J'ai eu un peu de mal à trouver une fonction bash qui enveloppe la réponse de Peter Tillemans, mais voici ce que j'ai proposé:
fonction regex {Perl -n -e "/ $ 1/&& printf \"% s\n\"," '$ 1'}
J'ai trouvé que cela fonctionnait mieux que la fonction bash basée sur awk de opsb pour l'argument d'expression régulière suivant, car je ne souhaite pas que le "ms" soit imprimé.
'([0-9]*)ms$'