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?


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:~$

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}

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}

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

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 :)


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.


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.


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

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

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!


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

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

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.


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'

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"}'


1

Essaye celui-là:

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

Va créer (cent tirets):


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.