Commande Linux pour répéter une chaîne n fois

71

Existe-t-il une commande Linux intégrée permettant de générer une chaîne représentant n fois une chaîne d'entrée?

GetFree
la source
1
Par "commande linux intégrée", je suppose que vous entendez une commande shell, et puisque vous ne mentionnez pas le shell que vous utilisez, je suppose que c'est bash. Vous pouvez vérifier cela en tapant "echo $ SHELL" sur la ligne de commande et vous devriez obtenir quelque chose de similaire à "/ bin / bash". Si vous ne le faites pas, vous devriez modifier votre réponse pour spécifier ce qu'elle montre. A bientôt :)
Adrian Petrescu
7
J'ai tagué la question avec "bash". Je pensais que cela aurait suffi.
GetFree

Réponses:

75
adrian@Fourier:~$ printf 'HelloWorld\n%.0s' {1..5}
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$
Adrian Petrescu
la source
3
Pourriez-vous expliquer comment cela fonctionne? Je comprends la commande printf car elle est identique à celle de C / C ++. Mais je ne comprends pas comment le {1..5} est développé et comment cela fonctionne conjointement avec la partie "% .0s".
GetFree
4
C'est un peu un bidouillage :) Essayez de lancer "printf 'HelloWorld% d \ n' 1 2 3 4 5" et ça cliquera probablement pour vous. Le drapeau% .0s est censé ne rien faire, soyez juste là pour ramasser des arguments. Ensuite, si bash reçoit plus d’arguments que de spécificateurs de format, il en imprimera simplement plusieurs copies, en en prenant autant que nécessaire. Donc, vous obtenez l'effet. La sortie de "printf 'HelloWorld% d% d \ n' 1 2 3 4 5 6" le rend probablement encore plus clair. J'espère que cela t'aides!
Adrian Petrescu
Je vois. C'est le comportement particulier de printf qui permet la répétition
GetFree
1
(Je devrais noter que, d’un point de vue purement théorique, il s’agit probablement de la solution la plus rapide, car elle utilise une seule primitive de shell, pas de processus externes. En réalité, l’exécution des scripts bash importe peu: )
Adrian Petrescu
1
Ce qui est spécifique, printfc'est qu'il appliquera de manière répétée des arguments en excès à la chaîne de formatage, "en boucle" gratuitement. Par "excès", je veux dire qu'il y a plus d'arguments que de caractères %génériques.
Dennis Williamson
69

Voici une manière démodée qui est assez portable:

yes "HelloWorld" | head -n 10

Ceci est une version plus conventionnelle de la réponse d' Adrian Petrescu en utilisant une extension d'accolade:

for i in {1..5}
do
    echo "HelloWorld"
done

Cela équivaut à:

for i in 1 2 3 4 5

Voici une version un peu plus concise et dynamique de la réponse de pike :

printf -v spaces '%*s' 10 ''; printf '%s\n' ${spaces// /ten}
Dennis Williamson
la source
Comment vous débarrasser des nouvelles lignes lorsque vous utilisez la commande yes?
GetFree
3
Une façon de le faire passer sed -n 'H;${x;s/\n//gp}'ou sed -n ':t;${s/\n//gp};N;bt'une autre consiste à echo $(yes "HelloWorld" | head -n 10)ajouter un espace entre chaque copie de la chaîne. Une autre méthode consiste à diriger le message à travers tr -d '\n'ce qui élimine également la nouvelle ligne finale.
Dennis Williamson
2
C'est comme Haskell dans un shell bash: Hashell?
wchargin
4
La solution du oui est plutôt
chouette
La yessolution était exactement ce dont j'avais besoin, car je voulais dupliquer une commande (dont le résultat fluctue). Ainsi:yes "$(my-command)" | head -n 2
arnsholt
14

Ceci peut être paramétré et ne nécessite pas de variable temporaire, FWIW:

printf "%${N}s" | sed 's/ /blah/g'

Ou, si $Nest la taille d'un tableau bash:

echo ${ARR[@]/*/blah}
Twifkak
la source
3
Ceci est le plus court Posix 7 solution que je l' ai vu jusqu'à présent depuis seq, yeset {1..5}ne sont pas 7. POSIX
Ciro Santilli新疆改造中心法轮功六四事件
Vous ne devriez pas mélanger les données dans printfle spécificateur de format de. Et si les données contiennent des chaînes de format? C'est la bonne façon de spécifier dynamiquement la "précision" (longueur): printf '%*s' "$N"- prenez l'habitude de mettre la chaîne de format entre guillemets simples pour empêcher le développement de variables à cet endroit.
Dennis Williamson
13

Quelques bonnes manières déjà mentionnées. Je ne peux pas oublier le bon vieux seqsi:

[john @ awesome] $ pour i dans `seq 5`; echo "Salut" fait
salut
salut
salut
salut
salut
John T
la source
Celui-ci respecte réellement un zéro, en le traitant comme zéro! (L' {i..j}astuce ne retourne jamais une plage vide.)
JellicleCat
10

Peut-être une autre manière plus générale et utile pour vous:

adrian@Fourier:~$ n=5
adrian@Fourier:~$ for (( c=1; c<=n; c++)) ; do echo "HelloWorld" ; done
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$ 

Le shell bash est plus puissant que la plupart des gens pensent :)

Adrian Petrescu
la source
Cela obtient mon vote, car il est entièrement interne à la coquille; pas de forçage requis.
esm
2
De quelle fourche faites-vous allusion? La réponse originale n'en nécessite aucune. Le résultat de 'type printf' est 'printf est un shell intégré' et s'exécute donc dans le processus bash d'origine.
CodeGnome
Ceci est le seul jusqu'à présent ( yes, printf, for i in {1..5}) que si le nest égal à zéro, elle renvoie une chaîne vide , sans statut existe 1. Aussi en raison de la notation mathématique de comparaison, il est facile d'avoir compensé par 1 (par exemple en changeant la <=à <)
Mehrad Mahmoudian le
10

Vous pouvez utiliser un truc. Faire écho à une variable vide n’imprime rien. Pour que vous puissiez écrire:

echo word$wojek{1..100}

Si $wojek1 $wojek2... $wojek100sont des variables non existantes, votre mot sera répété 100 fois sans rien d'autre.

Wojciech Waga
la source
1
C'est un vilain bidule moche, et pourtant je ne peux m'empêcher de l'aimer et de l'utiliser.
16807
Aimer! Peut-être qu'utiliser $_plutôt que de $wojekrendre l'intention plus claire.
Mihai Todor le
7

Répétez nfois, il suffit de mettre des n-1virgules entre {}:

$ echo 'helloworld'{,,}
helloworld helloworld helloworld

Répète "helloworld" deux fois après le premier écho.

kev
la source
5
Bien, mais si je veux obtenir nune variable?
GetFree
1
il ajoute un espace supplémentaire après chaque 'helloworld'
PADYMKO
cela ne semble pas vous laisser mettre de nouvelles lignes dans la chaîne non plus (c'est-à-dire obtenir helloworld sur leurs propres lignes)
TankorSmash
5
awk 'BEGIN {while (c++<4) printf "Hello"}'

Résultat

Bonjour bonjour bonjour bonjour
Steven Penny
la source
Utilisez ceci sans l'awk: while ((c ++ <5)); faire printf 'bonjour'; fait
emf
4

J'ai rencontré des avertissements de rupture de tuyau avec la yessolution, alors voici une autre bonne alternative:

$ seq 4 | sed "c foo"
foo
foo
foo
foo
n.caillou
la source
3

basé sur ce que @pike faisait allusion à

pour chaque caractère d'une chaîne chaîne d'écho

echo ${target//?/$replace}

Un exemple de rubrique soulignée de =caractères

export heading='ABCDEF'; 
export replace='='; 
echo -e "${heading}\n${heading//?/$replace}"

va sortir

ABCDEF
======

Cela semble porter entre Linux et OS X et cela me rend heureux.

NonJoy!

Nickl
la source
3

Si vous êtes sur BSD, vous pouvez simplement utiliser seq.

$ seq -f "Hello, world" 5
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Qix
la source
1
In seq (GNU coreutils) 8.25, cela donne seq: format 'Hello, world' has no % directive, obligeant une directive de formatage à être présent. Les coreutils GNU sont utilisés, par exemple dans de nombreuses distributions Linux et Cygwin. Y compris l'info ici pour ceux qui manquent l'info qu'il fonctionne uniquement dans BSD seq.
Palec
2
line="==========================="
line=${line:0:10}
${line//"="/"ten "}

les sorties

ten ten ten ten ten ten ten ten ten ten
brochet commun
la source
Peut-être un exemple plus détaillé: declare c = '-----'; c = $ {c // $ {c: 0: 1} / $ c}; echo $ c # Imprime "-" 25 fois.
Stephen Niedzielski
2

En supposant que vous souhaitiez quelque chose comme l' xopérateur Perl , où vous ne recevez pas automatiquement de nouvelle ligne entre les répétitions:

x() {
  # usage: x string num
  for i in $(seq 1 $2); do printf "%s" "$1"; done
  # print a newline only if the string does not end in a newline
  [[ "$1" == "${1%$'\n'}" ]] && echo ""
}

x Hi 10  # ==> HiHiHiHiHiHiHiHiHiHi

x $'Hello World!\n' 3

J'ai explicitement utilisé une forboucle parce que vous ne pouvez pas écrire {1..$n}dans bash: le développement d'accolade est effectué avant la substitution de variable.

Glenn Jackman
la source
2

Pas exactement intégré à linux, mais si vous avez installé python ..

python
>>>var = "string"
>>>var*n

Ou en une ligne, comme l'a suggéré le commentateur:

python -c 'print "This is a test.\n" * 10'
eqzx
la source
4
Pas vraiment utile, car il ne peut pas être facilement intégré dans des scripts shell, etc. Et puisqu'il y a environ un milliard de façons de faire cela dans le shell lui-même, je ne vois aucune raison de faire ressortir les gros canons (c'est-à-dire Python). .
Adrian Petrescu
7
Je suis d'accord avec votre deuxième point, mais pas avec le poing ... il est facile à intégrer dans un script shell: python -c 'print "Ceci est un test. \ N" * 10'
larsks
J'aime la lisibilité de cette solution, une raison suffisante pour moi. ;)
elias
2

Pas de magie ici:

seq 5 | awk '{print "Hello World"}'

brablc
la source
1

Essaye celui-là:

echo $(for i in $(seq 1 100); do printf "-"; done)

Va créer (cent tirets):


Alle Aldine
la source