Awk compréhension d'une commande

Résolu
lenainjaune Messages postés 720 Date d'inscription   Statut Contributeur Dernière intervention   -  
dubcek Messages postés 18806 Date d'inscription   Statut Contributeur Dernière intervention   -

Bonjour à tou.te.s :) !

En vue de filtrer une sortie de transcription brute d'une vidéo avec l'outil yt-dlp, je suis tombé sur cette solution pleinement fonctionnelle : 

awk '

# Checking condition if line number is less than 4
# OR having spaces or [ or ] or --> then go next line.     
FNR<=4 || ($0 ~ /^$|-->|\[|\]|</){

  # next will skip all further statements from here.
  next                                    
  }
  
# Creating an array whose index is $0 and increment 
# its value with 1 with condition that it should NOT 
# be already present in array a, which means it will 
# give only 1 value of each line.
!a[$0]++

# Mentioning Input_file name here.                                  
'  Input_file

Dans :

!a[$0]++ # Comment que ça marche pour de vrai ?

Qu'est ce qu'on incrémente, vu qu'on utilise un tableau associatif ?

Si je comprends bien, toutes les fois où l'ajout échoue (!) car étant déjà présent, on consomme une écriture et donc on n'affiche rien. Au final, on affichera uniquement quand l'index associatif n'existe pas encore. C'est bien ça ?

Je précise que si j'avais eu à le faire en utilisant un tableau associatif, le script aurait été d'avantage étoffé !

Bref, si quelqu'un d'un peu expérimenté peut m'expliquer la syntaxe de cette expression assez cryptique pour moi.

Avec adelphité,

lnj


Linux / Firefox 147.0


A voir également:

3 réponses

dubcek Messages postés 18806 Date d'inscription   Statut Contributeur Dernière intervention   5 648
 

tu as tout compris

en ajoutant que si il n'y a pas de code à droite du test, le défaut est { print $0 }

1
dubcek Messages postés 18806 Date d'inscription   Statut Contributeur Dernière intervention   5 648
 

Hello

on utiise $0, donc le contenu de la ligne, comme index

ça permet, par exemple, de compter les lignes identiques

on peut afficher le tableau, en fin de traitement, avec une boucle for

n prend la valeur de chaque index, dans ton exemple, de chaque ligne

END{for(n in a)print n, a[n]}

exemple 

$ cat f
aa
bb
bb
aa
cc
$ awk '{!a[$0]++} END{for(n in a)print n, a[n]}' f
bb 2
cc 1
aa 2
$ 

0
dubcek Messages postés 18806 Date d'inscription   Statut Contributeur Dernière intervention   5 648
 

sous cette forme, n'affiche qu'une occurrence de chaque ligne

$ cat f
aa
bb
bb
aa
cc
$ awk '!a[$0]++' f
aa
bb
cc
$ 
0
lenainjaune Messages postés 720 Date d'inscription   Statut Contributeur Dernière intervention   62
 

Oups je t'ai oublié. Merci pour ton aide @dubcek StatutContributeur ;)

Ça y est je crois que j'ai compris :D

Dans le corps de awk, pour la règle suivante :

# Règle sans action
!a[$0]++

Dans le bloc de corps de awk, le principe est d'effectuer séquentiellement des actions selon des règles. Si une règle n'existe pas, étant considérée comme vraie tout le temps (ou 1), l'action s'exécute sans condition. L'action par défaut étant d'afficher la rangée en cours (row) si elle n'est pas explicitement implémentée.

Note : je dis rangée et pas ligne, car ligne limiterait la compréhension à du texte écrit entre 2 sauts de lignes (cas habituel mais particulier quand même)

En incrémentant dans un tableau associatif table une association inexistante d'indice cle avec table["cle"]++, on force la valeur d'indice "cle" de table à lui associer un entier (par défaut sa valeur est à 0, donc après incrémentation 1) ; ainsi après exécution de la règle, table["cle"] contient désormais 1

Je n'ai pas retrouvé dans le manuel, mais j'en ai déduis que si l'indice existe déjà, donc l'association est déjà effectuée, l'opération d'incrémentation s'effectuera quand même, mais en retournant faux puisque déjà existant. Inversement, si l'association n'existe pas pour cet indice, l'opération retourne vrai.

Quand l'opération s'effectue sur une association existante, elle renvoie faux et comme la règle demande l'inverse !... cela la rend vrai. On exécute ainsi l'action qui puisqu'elle n'est pas implémentée, ne fera qu'afficher la rangée en cours.

Au final, j'affiche la rangée en cours que si l'association n'a pas encore été effectuée pour cet indice.

J'espère avoir bien compris, en tout cas, ça commence à devenir une évidence, même si je ne sais pas bien l'expliquer.

0