Question

Existe-t-il un moyen de déterminer si la ligne en cours est la dernière ligne du flux d'entrée?

Était-ce utile?

La solution

Vous avez deux options, les deux en désordre.

  1. Stockez une copie de chaque ligne en cours dans une variable temporaire, puis utilisez le bloc END pour la traiter.
  2. Utilisez la commande système pour exécuter " wc -l | getline " dans le bloc BEGIN pour obtenir le nombre de lignes du fichier, puis comptez cette valeur.

Vous devrez peut-être jouer un peu avec le n ° 2 pour le faire fonctionner, mais cela devrait fonctionner. Cela fait longtemps que je n’ai pas fait de bêtise.

Autres conseils

Le modèle spécial END ne correspond qu'après la fin de toutes les entrées . Notez que ce modèle ne peut être combiné avec aucun autre.

Plus utile est probablement la pseudo-fonction getline qui réinitialise $ 0 à la ligne suivante et renvoie 1, ou dans le cas où EOF renvoie 0! Ce que je pense est ce que vous voulez.

Par exemple:

awk '{ if(getline == 0) { print "Found EOF"} }'

Si vous ne traitez qu'un seul fichier, cela équivaut à:

awk 'END { print "Found EOF" }'

Ce sont les seuls moyens sensés de faire ce que vous voulez, par ordre croissant de résultats:

awk 'NR==FNR{max++; next} FNR == max { print "Final line:",<*> }' file file

awk -v max="$(wc -l < file)" 'FNR == max { print "Final line:",<*> }' file

awk 'BEGIN{ while ( (getline dummy < ARGV[1]) > 0) max++; close(ARGV[1])} FNR == max { print "Final line:",<*> }' file

La détection du fichier EOF n’est pas trop fiable lorsque plusieurs fichiers sont en ligne de commande. Détecter le début du fichier est plus fiable.

Pour ce faire, le premier fichier est spécial et nous ignorons le FNR == 1.

Après le premier fichier, FNR == 1 devient la fin du fichier précédent. last_filename a toujours le nom de fichier que vous traitez.

Faites votre traitement de fichier après l'autre.

Effectuez votre traitement EOF dans le bloc else, ET dans le bloc END.

   gawk 'BEGIN{last_filename="";} \
      FNR==1{if (last_filename==""){last_filename=FILENAME;} \
      else {print "EOF: "last_filename;last_filename=FILENAME;}} \
      END{print "END: "last_filename;}' $*

Pour plusieurs ensembles de fichiers, le bloc else s'exécute à EOF pour tous sauf le dernier fichier. Le dernier fichier est exécuté dans le bloc END.

Pour les ensembles de fichiers uniques, le bloc else n'est pas exécuté et le bloc END est exécuté.

Je ne sais même pas comment catégoriser cette "solution"

{
    t = lastline
    lastline = <*>
    <*> = t
}

/test/ {
    print "line <" <*> "> had a _test_"
}

END {
    # now you have "lastline", it can't be processed with the above statements
    # ...but you can work with it here
}

La chose intéressante à propos de ce hack est qu’en assignant à $ 0 , tous les modèles et actions déclaratifs restants fonctionnent, avec une ligne en retard. Vous ne pouvez pas les faire fonctionner pour END , même si vous placez le FIN au-dessus, mais vous avez le contrôle sur le dernier ligne et vous n'avez rien fait d'autre.

La

implémentation de gawk a une règle spéciale appelée ENDFILE qui sera déclenchée. après traitement de chaque fichier dans la liste d'arguments. Cela fonctionne:

awk '{line=<*>} ENDFILE {print line}' files...

Plus de détails, vous trouverez ici > >

Une méthode simple consiste à exécuter le fichier via un script intermédiaire sed , qui place un 0 sur chaque dernière ligne et un 1 sur la dernière.

cat input_file | sed 's/^/0/;$s/0/1/' | awk '{LST=/^1/;<*>=substr(<*>,2)}
... your awk script in which you can use LST to check for the
... last line.'

Pour détecter la dernière ligne de chaque fichier dans la liste des arguments ce qui suit fonctionne bien:

FNR == 1 || EOF {
  print "last line (" FILENAME "): " <*>
}

Hmm, la variable awk END indique quand vous avez déjà atteint le EOF . Je ne vous aide pas beaucoup, je suppose

vous pouvez essayer ceci:

awk 'BEGIN{PFNR=1} FNR==PFNR{PFNR++;next} {print FILENAME,PFNR=2} END{print FILENAME}' file1 file2

Une solution portable est fournie dans la Le manuel d'utilisation de gawk , bien que, comme indiqué dans une autre réponse, gawk comporte lui-même BEGINFILE et ENDFILE.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top