11
votes

Comment détecter eof dans awk?

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


0 commentaires

11 Réponses :


0
votes

hmm the awk fin variable indique lorsque vous avez déjà atteint le eof . N'est pas vraiment une grande partie de l'aide pour vous, je suppose


1 commentaires

S'il y a plusieurs fichiers, fin s'exécutera une fois à la fin du dernier fichier.



9
votes

Vous avez deux options, les deux types de messy.

  1. Stockez une copie de chaque ligne actuelle dans une variable TEMP, puis utilisez le bloc de fin pour le traiter.
  2. Utilisez la commande système pour exécuter "wc -l | getline" dans le bloc de début pour obtenir le nombre de lignes dans le fichier, puis compter la valeur de cette valeur.

    Vous pourriez avoir à jouer avec # 2 un peu pour le faire courir, mais cela devrait fonctionner. Sa fait un moment depuis que j'ai fait n'importe quel awk.


3 commentaires

Yuck, je déteste vraiment cette option 2. Mais l'option 1 est la façon de le faire. +1 pour l'option 1.


Non! Ne faites pas l'option "1", car c'est un gaspillage de ressources et ne pas faire l'option "2" car c'est simplement la mauvaise façon d'utiliser WC dans ce scénario et introduit toutes les réserves de goulotte.


Si le fichier doit rester la même longueur de ligne, vous pouvez faire enregistrements = $ (myfile de chat | wc -l); awk 'nr ==' $ {enregistrements} '{imprimé "dernière ligne"}' myfile . Hé, au point où vous choisissez Awk, vous êtes déjà passé de côté l'élégance. :)



13
votes

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

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

Par exemple: xxx

Si vous ne traiterez qu'un seul fichier, ce serait équivalent: xxx


3 commentaires

En fait, mon premier exemple devrait lire: awk '{alors que (getline == 1) {}; Imprimer "trouvé eof"} '


Vrai, oublié de mentionner cela, mais s'il lisait un tas de fichiers statiques, cela est peu probable, mais je suppose que cela dépend beaucoup sur le contexte de son script.


Merci! Si on traite avec deux fichiers, alors on peut faire cmd = "fichier de chat2"; tandis que (condition) {if (cmd | getline ligne2 == 0) casse;



2
votes

Je ne suis même pas sûr comment classer cette "solution" xxx

La chose cool à propos de ce piratage est qu'en attribuant à 0 $ 0 , tout le reste Les modèles déclaratifs et les actions fonctionnent, une ligne différée. Vous ne pouvez pas les amener à travailler pour le fin , même si vous mettez le fin en haut, mais vous do avez le contrôle sur le dernier ligne et vous n'avez rien fait d'autre à cela.


1 commentaires

Cela ne détecte-t-il que la dernière ligne du dernier fichier de la liste des fichiers d'entrée AWK?



2
votes

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 "): " $0
}


0 commentaires

1
votes

Un moyen facile consiste à exécuter le fichier via un script intermédiaire SED code>, qui place un 0 sur chaque ligne non dernière ligne et 1 sur le dernier.

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


1 commentaires

Première version à l'aide de SED que j'ai trouvé cela fonctionne réellement et, dans mon cas, je ne voulais pas utiliser Awk du tout.



7
votes

Ce sont les seuls moyens sensibles de faire ce que vous voulez, par ordre de mieux à pire: xxx


0 commentaires

4
votes

La détection de l'EOF n'est pas trop fiable lorsque plusieurs fichiers sont sur la ligne de commande. La détection du début du fichier est plus fiable.

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

après le premier fichier, puis fnr == 1 devient la fin du fichier précédent. last_filename a toujours le nom de fichier que vous traitez. p>

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

Faites votre traitement EOF à l'intérieur du bloc d'enseil et dans le bloc d'extrémité. P >

   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;}' $*


0 commentaires

0
votes

Vous pouvez essayer ceci:

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


0 commentaires

4
votes

Mise en œuvre GAWK a une règle spéciale appelée endfile qui sera déclenché Après avoir traité chaque fichier dans la liste des arguments. Cela fonctionne: xxx

Plus de détails Vous pouvez trouver ici >>


0 commentaires

0
votes

Une solution portable est fournie dans le Manuel d'utilisation de Gawk , bien que mentionné dans une autre réponse, Gawk elle-même a débutant et findfile.


0 commentaires