• # Une explication

    Posté par . En réponse au message Awk : Besoin d'explications. Évalué à 10.

    Bonjour,

    La commande complète et ce qui est attendu:

    $ echo FIELDA01VALUEA01FIELDA21VALUEA21FIELDA31VALUEA3 |awk -F1 '/FIELDA2/{f=NR} f&&NR-1==f' RS="1"
    FIELDA2
    

    Pour comprendre comment ça marche, le plus simple, ici, est de l'exécuter morceau par morceau en affichant les valeurs des variables:

    • Dans un premier temps, le RS="1" est vrai tout au long du programme. Le caractère "1" remplace le retour à la ligne (\n) pour séparer les Records (une ligne en temps normal).
    $ echo FIELDA01VALUEA01FIELDA21VALUEA21FIELDA31VALUEA3 |awk '{print}' RS="1"
    FIELDA0
    VALUEA0
    FIELDA2
    VALUEA2
    FIELDA3
    VALUEA3
    
    • Ensuite, chaque expression est constituée d'un motif (Pattern) et d'une action. Nous en avons 2:
    Motif n°1: /FIELDA2/ Action n°1: {f=NR} 
    Motif n°2: f&&NR-1==f Action n°2: Absente, donc {print}
    
    • Le motif n°1 est une expression régulière qui sera vraie si la ligne contient "FIELDA2". Dans ce cas, l'action assignera le numéro de ligne courant NR à f.
    $ echo FIELDA01VALUEA01FIELDA21VALUEA21FIELDA31VALUEA3 |awk '/FIELDA2/{f=NR} ; END{print f}'
    5
    
    • Comme f contient le numéro de ligne de la clef recherchée, reste à afficher la ligne suivante qui contient la valeur. Elle est sélectionnée par f&&NR-1==f qui s'écrit f && ( (NR-1) == f). Considérons seulement (NR-1)==f, cette expression est vraie 2 fois, une avant l'assignation de la première expression, l'autre après.
    $ echo FIELDA01VALUEA01FIELD31VALUE31FIELDA21VALUEA21FIELDA31VALUEA3 |awk '/FIELDA2/{f=NR} ; (NR-1==f){print NR, f, 0ドル}' RS="1"
    1 FIELDA0
    6 5 VALUEA2
    

    Donc on se protège en vérifiant que f est assigné: ( ( f ) && ( ( NR -1 ) == f ) )

    On peut donc écrire le programme comme

    BEGIN{ RS="1" ; f="" ; }
    /FIELDA2/{ f=NR ; }
    (f && ( ( NR -1 ) == f) ) { print; }
    

    Note: Le séparateur "1" n'est pas très bien choisi (pas de FIELDA1)