Avec tcshou zsh, repeat 5000 printf Hest plus facile à comprendre. Avec perl: print "H" x 5000(notez que {1..5000}c'est un opérateur zsh inspiré par perll » 1..5000un, puis copié par ksh93 et bash)
Stéphane Chazelas
oui cela fonctionne, mais utilise beaucoup de ressources pour une plus grande répétition, suivez les suggestions de Stéphane Chazelas
Skaperen
1
je ferais cette commandeyes H|head -5000|tr -d '\012'
Skaperen
dd if=/dev/zero bs=5000 count=1 | tr '\0' H
kojiro
@Skaepren:yes H| head -n 2500| tr \\n H
mikeserv
Réponses:
20
Cette commande dépend du shell qui génère 5000 arguments et les transmet à printfqui les ignore ensuite. Bien que cela puisse sembler assez rapide - et est relatif à certaines choses - le shell doit toujours générer toutes ces chaînes en tant qu'args (et les délimiter) et ainsi de suite.
Outre le fait que les H générés ne peuvent pas être imprimés avant que le shell n'itère pour la première fois à 5000, cette commande coûte également en mémoire tout ce qu'il faut pour stocker et délimiter les arguments de chaîne numérique en printfplus des H. Vous pouvez tout aussi simplement faire:
printf %05000s|tr \ H
... qui génère une chaîne de 5000 espaces - qui, au moins, ne sont généralement qu'un seul octet par et ne coûtent rien à délimiter car ils ne sont pas délimités. Quelques tests indiquent que même pour aussi peu que 5000 octets, le coût de la fourche et du tuyau requis en trvaut la peine, même dans ce cas, et c'est presque toujours lorsque les chiffres augmentent.
J'ai couru...
time bash -c 'printf H%.0s {1..5000}'>/dev/null
...et...
time bash -c 'printf %05000s|tr \ H'>/dev/null
Chaque fois environ 5 fois une pièce (rien de scientifique ici - seulement anecdotique) et la version d'extension de l'accolade en moyenne un peu plus de 0,02 seconde de temps de traitement total, mais la trversion est arrivée à environ 0,012 seconde au total en moyenne - et la trversion l' a battu à chaque fois. Je ne peux pas dire que je suis surpris - {brace expansion}est une fonctionnalité raccourcie interactive du shell, mais c'est généralement une chose plutôt inutile à faire pour tout type de script. La forme commune:
for i in{[num]..[num]};do...
... quand vous y pensez, il y a vraiment deuxfor boucles - la première est interne et implique que le shell doit boucler d'une manière ou d'une autre pour générer ces itérateurs avant de les enregistrer tous et de les réitérer pour votre forboucle. De telles choses sont généralement mieux faites comme:
... car vous ne stockez que très peu de valeurs et les écrasez au fur et à mesure ainsi que l'itération pendant que vous générez les itérables.
Quoi qu'il en soit, comme le remplissage d'espace mentionné précédemment, vous pouvez également utiliser printfpour zéros un nombre arbitraire de chiffres, bien sûr, comme:
printf %05000d
Je fais les deux sans arguments parce que pour chaque argument spécifié dans printfla chaîne de format de quand un argument n'est pas trouvé, la chaîne nulle est utilisée - ce qui est interprété comme un zéro pour un argument numérique ou une chaîne vide pour une chaîne.
C'est l'autre côté (et - à mon avis - plus efficace) de la pièce par rapport à la commande dans la question - alors qu'il est possible de ne rien obtenir de quelque chose comme vous le faites lorsque vous printf %.0longueurz des chaînes pour chaque argument, il en va de même pour il est possible de tirer quelque chose de rien.
Plus rapide encore pour de grandes quantités d'octets générés que vous pouvez utiliser ddcomme:
printf \\0| dd bs=64k conv=sync
... et w / fichiers réguliers de ddl » seek=[num]argument peut être utilisé pour plus grand avantage. Vous pouvez obtenir 64 000 sauts de ligne plutôt que des valeurs nulles si vous ajoutez ,unblock cbs=1à ce qui précède et à partir de là, vous pouvez injecter des chaînes arbitraires par ligne avec pasteet /dev/null- mais dans ce cas, s'il est disponible, vous pouvez aussi utiliser:
yes 'output string forever'
Voici ddquand même quelques exemples:
dd bs=5000 seek=1if=/dev/null of=./H.txt
... qui crée (ou tronque) un \0NULfichier rempli dans le répertoire courant nommé H.txt de taille 5000 octets. ddrecherche directement le décalage et remplit NUL tout derrière.
<&1 dd bs=5000 conv=sync,noerror count=1| tr \\0 H >./H.txt
... qui crée un fichier du même nom et de la même taille mais rempli de caractères H / H. Il tire parti du ddcomportement spécifié par l'écriture d'au moins un bloc nul complet en cas d'erreur de lecture lorsque noerroret les syncconversions sont spécifiées (et - sans count=- continuerait probablement plus longtemps que vous ne le souhaiteriez) , et redirige intentionnellement un descripteur de fichier en écriture seule sur ddstdin.
Le %.0smoyen de convertir l'argument sous forme de chaîne , avec une précision de zéro. Selon man 3 printf, la valeur de précision dans un tel cas donne
[...] the maximum number of characters to be printed from a
string for s and S conversions.
par conséquent, lorsque la précision est nulle, l' argument chaîne n'est pas imprimé du tout. Cependant, le H(qui fait partie du spécificateur de format) est imprimé autant de fois qu'il y a d'arguments, car selon la printfsection deman bash
The format is reused as necessary to consume all of the argu‐
ments.If the format requires more arguments than are supplied,
the extra format specifications behave as if a zero value or
null string, as appropriate, had been supplied.
Dans ce cas, %.0simprime toujours une instance de caractère (s) qui le précède, H dans ce cas. Lorsque vous utilisez {1..5000}, le shell le développe et il devient:
printf 'H%.0s'1234...5000> H.txt
c'est-à-dire que la commande printf a maintenant 5000 arguments, et pour chaque argument, vous obtiendrez un H. Ceux-ci ne doivent pas être séquentiels ou numériques:
printf 'H%.0s' a bc fg 1234
imprime HHHHH- c'est-à-dire le nombre d'arguments, 5 dans ce cas.
Notez que les ellipses dans le 1er exemple ci-dessus ne sont pas insérées littéralement, elles sont là pour indiquer une séquence ou une plage.
tcsh
ouzsh
,repeat 5000 printf H
est plus facile à comprendre. Avecperl
:print "H" x 5000
(notez que{1..5000}
c'est un opérateur zsh inspiré parperl
l »1..5000
un, puis copié par ksh93 et bash)yes H|head -5000|tr -d '\012'
dd if=/dev/zero bs=5000 count=1 | tr '\0' H
yes H| head -n 2500| tr \\n H
Réponses:
Cette commande dépend du shell qui génère 5000 arguments et les transmet à
printf
qui les ignore ensuite. Bien que cela puisse sembler assez rapide - et est relatif à certaines choses - le shell doit toujours générer toutes ces chaînes en tant qu'args (et les délimiter) et ainsi de suite.Outre le fait que les H générés ne peuvent pas être imprimés avant que le shell n'itère pour la première fois à 5000, cette commande coûte également en mémoire tout ce qu'il faut pour stocker et délimiter les arguments de chaîne numérique en
printf
plus des H. Vous pouvez tout aussi simplement faire:... qui génère une chaîne de 5000 espaces - qui, au moins, ne sont généralement qu'un seul octet par et ne coûtent rien à délimiter car ils ne sont pas délimités. Quelques tests indiquent que même pour aussi peu que 5000 octets, le coût de la fourche et du tuyau requis en
tr
vaut la peine, même dans ce cas, et c'est presque toujours lorsque les chiffres augmentent.J'ai couru...
...et...
Chaque fois environ 5 fois une pièce (rien de scientifique ici - seulement anecdotique) et la version d'extension de l'accolade en moyenne un peu plus de 0,02 seconde de temps de traitement total, mais la
tr
version est arrivée à environ 0,012 seconde au total en moyenne - et latr
version l' a battu à chaque fois. Je ne peux pas dire que je suis surpris -{brace expansion}
est une fonctionnalité raccourcie interactive du shell, mais c'est généralement une chose plutôt inutile à faire pour tout type de script. La forme commune:... quand vous y pensez, il y a vraiment deux
for
boucles - la première est interne et implique que le shell doit boucler d'une manière ou d'une autre pour générer ces itérateurs avant de les enregistrer tous et de les réitérer pour votrefor
boucle. De telles choses sont généralement mieux faites comme:... car vous ne stockez que très peu de valeurs et les écrasez au fur et à mesure ainsi que l'itération pendant que vous générez les itérables.
Quoi qu'il en soit, comme le remplissage d'espace mentionné précédemment, vous pouvez également utiliser
printf
pour zéros un nombre arbitraire de chiffres, bien sûr, comme:Je fais les deux sans arguments parce que pour chaque argument spécifié dans
printf
la chaîne de format de quand un argument n'est pas trouvé, la chaîne nulle est utilisée - ce qui est interprété comme un zéro pour un argument numérique ou une chaîne vide pour une chaîne.C'est l'autre côté (et - à mon avis - plus efficace) de la pièce par rapport à la commande dans la question - alors qu'il est possible de ne rien obtenir de quelque chose comme vous le faites lorsque vous
printf %.0
longueurz des chaînes pour chaque argument, il en va de même pour il est possible de tirer quelque chose de rien.Plus rapide encore pour de grandes quantités d'octets générés que vous pouvez utiliser
dd
comme:... et w / fichiers réguliers de
dd
l »seek=[num]
argument peut être utilisé pour plus grand avantage. Vous pouvez obtenir 64 000 sauts de ligne plutôt que des valeurs nulles si vous ajoutez,unblock cbs=1
à ce qui précède et à partir de là, vous pouvez injecter des chaînes arbitraires par ligne avecpaste
et/dev/null
- mais dans ce cas, s'il est disponible, vous pouvez aussi utiliser:Voici
dd
quand même quelques exemples:... qui crée (ou tronque) un
\0NUL
fichier rempli dans le répertoire courant nommé H.txt de taille 5000 octets.dd
recherche directement le décalage et remplit NUL tout derrière.... qui crée un fichier du même nom et de la même taille mais rempli de caractères H / H. Il tire parti du
dd
comportement spécifié par l'écriture d'au moins un bloc nul complet en cas d'erreur de lecture lorsquenoerror
et lessync
conversions sont spécifiées (et - sanscount=
- continuerait probablement plus longtemps que vous ne le souhaiteriez) , et redirige intentionnellement un descripteur de fichier en écriture seule surdd
stdin.la source
Le
%.0s
moyen de convertir l'argument sous forme de chaîne , avec une précision de zéro. Selonman 3 printf
, la valeur de précision dans un tel cas donnepar conséquent, lorsque la précision est nulle, l' argument chaîne n'est pas imprimé du tout. Cependant, le
H
(qui fait partie du spécificateur de format) est imprimé autant de fois qu'il y a d'arguments, car selon laprintf
section deman bash
la source
Dans ce cas,
%.0s
imprime toujours une instance de caractère (s) qui le précède, H dans ce cas. Lorsque vous utilisez {1..5000}, le shell le développe et il devient:c'est-à-dire que la commande printf a maintenant 5000 arguments, et pour chaque argument, vous obtiendrez un H. Ceux-ci ne doivent pas être séquentiels ou numériques:
imprime
HHHHH
- c'est-à-dire le nombre d'arguments, 5 dans ce cas.Notez que les ellipses dans le 1er exemple ci-dessus ne sont pas insérées littéralement, elles sont là pour indiquer une séquence ou une plage.
la source