2017-07-27 1 views
1

Il existe de nombreuses réponses à la première partie de la question, à savoir l'impression de lignes entre deux motifs. Par exemple:Imprimez des lignes entre deux motifs et dormez pendant une seconde puis répétez jusqu'à l'EOF

awk '/start/{flag=1} flag; /end/{flag=0}' file 

Cette imprime les lignes entre les motifs « start » et « fin » qui se produit à plusieurs reprises dans le « fichier ». Supposons que le fichier contient:

start a b c d 4 5 3 7 8 end some garbage start 6 d 0 0 1 d g end other garbages start 6 5 ... end some other garbage 

Les impressions de commande ci-dessus « awk » sur le fichier entier en éliminant les déchets .. ce qui est bien, mais ce que je veux est une pause entre chaque morceau. C'est imprimé

start a b c d 4 5 3 7 8 end

sommeil pour une seconde (sleep 1 peut être utilisé) puis imprimer le morceau suivant:

start 6 d 0 0 1 d g end 

et ainsi de suite jusqu'à la fin du fichier. J'ai beaucoup cherché mais je n'ai pas trouvé la seconde partie "pause/attente" donc je crois que ce n'est pas une question en double.

+1

Êtes-vous sûr que le script awk fait ce que vous dites qu'il est en train de faire? – JNevill

+1

Pour clarifier, cela ne fonctionne pas pour moi étant donné vos données d'échantillon et je ne peux pas voir comment cela fonctionnerait sans une boucle for pour itérer les champs dans l'enregistrement. Si une boucle for est implémentée, alors on pourrait, dans le test de '/ END /' implémenter un 'system (" sleep 10 ")' avant que la boucle ne passe au champ suivant. Mais c'est un point discutable puisque le script ne semble pas faire ce qu'il est censé faire. – JNevill

+0

@JNevill effectivement vous avez raison, il imprime l'ensemble du fichier. Mais de toute façon je ne suis pas intéressé par cette commande awk, ce n'était qu'un exemple. Ce que je veux je l'ai décrit dans la question. – quanta

Répondre

1

Avec awk GNU RS multi-CHAR:

$ cat tst.awk 
BEGIN { RS="[[:space:]]+"; ORS=" " } 
/start/ { found=1 } 
found { print } 
/end/ { printf "\n"; found=0; system("sleep 1") } 

$ time awk -f tst.awk file 
start a b c d 4 5 3 7 8 end 
start 6 d 0 0 1 d g end 
start 6 5 ... end 

real 0m3.214s 
user 0m0.015s 
sys  0m0.122s 

Notez que le nom de la variable doit être found ou un mot de la même sens, non flag comme un drapeau est quel type de variable, il est, pas ce qu'il représente. Nommer une variable de drapeau flag est comme nommer vos variables entières integer au lieu de count ou sum ou quelque chose d'autre significatif.

+0

Bonjour, il imprime toujours tout en une seule fois! Je veux quelque chose qui correspond à ces deux modèles (début et fin) et imprime un tel bloc et pause pendant une seconde, puis trouver le bloc suivant, etc – quanta

+0

Non, il ne fait pas, il fait exactement ce qu'il est montré à faire dans ma réponse. Si vous avez une expérience différente, votre contribution réelle ne correspond pas à votre contribution publiée ou vous n'utilisez pas gawk. –

1

Une alternative à l'utilisation system("sleep 1") comme suggéré par EdMorton serait à la sortie du tuyau awk dans une boucle bash while:

awk ... | while read -r line ; do 
    echo "${line}" 
    sleep 1 
done 

Cela éviterait de reproduire une coquille supplémentaire pour chaque opération de sommeil.

+0

Je ne vois pas les motifs "start" et "end" utilisés n'importe où, mais au moins il imprime des lignes simples donc c'est utile pour moi, bien que j'ai trouvé une autre solution très similaire à la vôtre: '#!/Bin/bash alors que IFS = '' read -r line || [[-n "$ ligne"]]; faire echo "$ line" sleep 1 done <"$ 1" 'merci beaucoup. – quanta

+0

Ce que je voulais dire, c'est utiliser le script awk d'EdMorten, retirer le 'system (" sleep 1 ")' de celui-ci et le diriger vers la boucle while.Mais c'est juste une très petite optimisation. La réponse d'EdMorten devrait fonctionner pour vous. – hek2mgl