Comando Linux per ripetere una stringa n volte


71

Esiste un comando Linux incorporato che consente di emettere una stringa che è n volte una stringa di input ??


1
Con "comando linux incorporato" presumo che tu intenda il comando shell, e dato che non dici quale shell stai usando, suppongo sia bash. Puoi verificarlo digitando "echo $ SHELL" nella riga di comando e dovresti ottenere qualcosa di simile a "/ bin / bash" indietro. In caso contrario, è necessario modificare la risposta per specificare ciò che mostra. Saluti :)
Adrian Petrescu il

7
Ho taggato la domanda con "bash". Ho pensato che sarebbe bastato.
GetFree il

Risposte:


75
adrian@Fourier:~$ printf 'HelloWorld\n%.0s' {1..5}
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$

3
Potresti spiegare come funziona? Capisco il comando printf poiché è lo stesso di quello in C / C ++. Ma non capisco come si espande {1..5} e come funzioni insieme alla parte "% .0s".
GetFree il

4
È un po 'un trucco :) Prova a eseguire "printf' HelloWorld% d \ n '1 2 3 4 5" e probabilmente farà clic per te. La bandiera% .0s non vuole fare nulla, basta essere lì per raccogliere argomenti. Quindi, se bash ottiene più argomenti di quanti ne abbia gli identificatori di formato, stamperà semplicemente più copie, catturandone quante ne ha bisogno. Quindi ottieni l'effetto. L'output di "printf 'HelloWorld% d% d \ n' 1 2 3 4 5 6" probabilmente lo rende ancora più chiaro. Spero che sia di aiuto!
Adrian Petrescu il

Vedo. È il comportamento particolare di printf ciò che consente la ripetizione
GetFree il

1
(Dovrei notare che, da un punto di vista puramente teorico, questa è probabilmente la soluzione più veloce poiché utilizza una singola shell primitiva - non alcun processo esterno. In realtà, ammettiamolo, le prestazioni degli script bash non contano davvero: )
Adrian Petrescu il

1
Ciò che è specifico printfè che applicherà ripetutamente argomenti in eccesso alla stringa di formato, "loop" gratuitamente. Per "eccesso" intendo che ci sono più argomenti che %segnaposto.
Dennis Williamson,

69

Ecco un modo vecchio stile che è abbastanza portatile:

yes "HelloWorld" | head -n 10

Questa è una versione più convenzionale della risposta di Adrian Petrescu usando l'espansione del controvento:

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

Ciò equivale a:

for i in 1 2 3 4 5

Questa è una versione un po 'più concisa e dinamica della risposta di Pike:

printf -v spaces '%*s' 10 ''; printf '%s\n' ${spaces// /ten}

Come si eliminano le nuove righe quando si utilizza il comando yes?
GetFree il

3
Un modo è di passarlo attraverso sed -n 'H;${x;s/\n//gp}'o sed -n ':t;${s/\n//gp};N;bt'un altro è fare ciò echo $(yes "HelloWorld" | head -n 10)che aggiunge uno spazio tra ogni copia della stringa. Ancora un altro modo è quello di convogliarlo, tr -d '\n'eliminando anche la nuova riga finale.
Dennis Williamson,

2
È come Haskell in una conchiglia: Hashell?
wchargin,

4
La soluzione sì è piuttosto ordinata
salvadanaio il

La yessoluzione era esattamente ciò di cui avevo bisogno, poiché volevo duplicare un comando (il cui output oscilla). Quindi:yes "$(my-command)" | head -n 2
arnsholt

14

Questo può essere parametrizzato e non richiede una variabile temporanea, FWIW:

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

Oppure, se $Nè la dimensione di un array bash:

echo ${ARR[@]/*/blah}

3
Questa è la soluzione POSIX 7 più corta che ho visto finora da allora seq, yese {1..5}non sono POSIX 7.
Ciro Santilli 10 改造 中心 法轮功 六四 事件

Non dovresti mescolare i dati printfnell'identificatore di formato. Cosa succede se i dati contengono stringhe di formato? Questo è il modo corretto di specificare dinamicamente la "precisione" (lunghezza): printf '%*s' "$N"- prendere l'abitudine di racchiudere la stringa di formato tra virgolette singole per impedire l'espansione variabile lì.
Dennis Williamson,

13

Parecchi buoni modi già menzionati. Non posso dimenticare il buon vecchio seqperò:

[john @ awesome] $ for i in `seq 5`; fai eco "Ciao"; fatto
Ciao
Ciao
Ciao
Ciao
Ciao

Questo in realtà rispetta uno zero, trattandolo come zero! (Il {i..j}trucco non restituisce mai un intervallo vuoto.)
JellicleCat

10

Forse un altro modo che è più generale e utile per te:

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

La shell bash è più potente di quanto la maggior parte della gente pensi :)


Questo ottiene il mio voto, poiché è interamente interno alla shell; nessun biforcazione richiesta.
esm,

2
A quale bivio ti riferisci? La risposta originale non richiede nessuno. L'output di 'type printf' è 'printf è una shell incorporata' e quindi viene eseguito all'interno del processo bash originale.
CodeGnome

Questo è l'unico finora ( yes, printf, for i in {1..5}) che se l' nè zero, restituisce stringa vuota senza esiste lo stato di 1. Anche a causa della notazione matematica per il confronto, è facile avere compensato da 1 (ad esempio modificando la <=a <)
Mehrad Mahmoudian il

10

Puoi usare un trucco. L'eco di una variabile vuota non stampa nulla. Quindi puoi scrivere:

echo word$wojek{1..100}

Se $wojek1 $wojek2... $wojek100sono variabili inesistenti, la parola verrà ripetuta 100 volte senza nient'altro.


1
È un brutto hack brutto, eppure non posso fare a meno di amarlo e usarlo.
16807,

Lo adoro! Forse usare $_invece di $wojekrendere più chiaro l'intento.
Mihai Todor

7

Ripeti i ntempi, inserisci solo le n-1virgole tra {}:

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

Ripete "helloworld" due volte dopo la prima eco.


5
Bello, ma cosa succede se voglio ottenere nda una variabile?
GetFree,

1
aggiunge uno spazio extra dopo ogni "mondo"
PADYMKO

questo non sembra che ti permetta di inserire nuove righe nella stringa (cioè ottenere helloworld sulle proprie linee)
TankorSmash

5
awk 'BEGIN {while (c++<4) printf "Hello"}'

Risultato

Ciao ciao ciao ciao

Usalo senza awk: while ((c ++ <5)); fare 'ciao' stampa; fatto
emf

4

Ho riscontrato avvisi di pipe non funzionanti con la yessoluzione, quindi ecco un'altra buona alternativa:

$ seq 4 | sed "c foo"
foo
foo
foo
foo

3

basato su ciò che @pike stava suggerendo

per ogni carattere nella stringa echo string

echo ${target//?/$replace}

Un esempio di intestazione sottolineata da =caratteri

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

uscirà

ABCDEF
======

Questo sembra port tra Linux e OS X e questo mi rende felice.

nJoy!


3

Se sei su BSD, puoi semplicemente usare seq.

$ seq -f "Hello, world" 5
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world

1
In seq (GNU coreutils) 8.25, questo dà seq: format 'Hello, world' has no % directive, forzando la presenza di una direttiva di formattazione. I coreutils GNU sono usati, ad esempio, in molte distribuzioni Linux e Cygwin. Includendo le informazioni qui per coloro che non hanno le informazioni che funzionano solo in BSD seq.
Palec,

2
line="==========================="
line=${line:0:10}
${line//"="/"ten "}

uscite

ten ten ten ten ten ten ten ten ten ten

Forse un esempio più dettagliato: declare c = '-----'; c = $ {c // $ {c: 0: 1} / $ c}; echo $ c # Stampa "-" 25 volte.
Stephen Niedzielski il

2

Supponendo di voler qualcosa come l' xoperatore di Perl , in cui non si ottiene automaticamente una nuova riga tra le ripetizioni:

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

Ho usato esplicitamente un forciclo perché non è possibile scrivere {1..$n}in bash: l'espansione del controvento viene eseguita prima della sostituzione delle variabili.


2

Non esattamente integrato in Linux, ma se hai installato Python ..

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

O in una riga, come suggerito dal commentatore:

python -c 'print "This is a test.\n" * 10'

4
Non molto utile, dal momento che non può essere facilmente integrato negli script della shell, ecc. E poiché ci sono circa un miliardo di modi per farlo nella shell stessa, vedo poche ragioni per far emergere le pistole grandi (cioè Python) .
Adrian Petrescu il

7
Sono d'accordo con il tuo secondo punto ma non con il pugno ... è facile da integrare in uno script di shell: python -c 'print "Questo è un test. \ N" * 10'
larsks

Mi piace la leggibilità di questa soluzione, una buona ragione sufficiente per me. ;)
elias,

2

Nessuna magia qui:

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


1

Prova questo:

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

Creerà (cento trattini):


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.