Comando Linux para repetir una cadena n veces

71

¿Existe algún comando de Linux incorporado que permita generar una cadena que sea n veces una cadena de entrada?

Liberarse
fuente
1
Por "comando de Linux incorporado" supongo que te refieres al comando de shell, y dado que no mencionas qué shell estás usando, supongo que es bash. Puede verificar esto escribiendo "echo $ SHELL" en la línea de comando y debería obtener algo similar a "/ bin / bash". Si no lo hace, debe editar su respuesta para especificar qué muestra. Saludos :)
Adrian Petrescu
77
Etiqueté la pregunta con "bash". Pensé que habría sido suficiente.
GetFree

Respuestas:

75
adrian@Fourier:~$ printf 'HelloWorld\n%.0s' {1..5}
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$
Adrian Petrescu
fuente
3
¿Podría explicar cómo funciona esto? Entiendo el comando printf ya que es el mismo que el de C / C ++. Pero no entiendo cómo se expande {1..5} y cómo funciona en conjunto con la parte "% .0s".
GetFree
44
Es un truco :) Intente ejecutar "printf 'HelloWorld% d \ n' 1 2 3 4 5" y probablemente haga clic para usted. El indicador% .0s está destinado a no hacer nada, solo estar allí para recoger argumentos. Luego, si bash obtiene más argumentos de los que tiene especificadores de formato, simplemente imprimirá varias copias, tomando todas las que necesite. Entonces obtienes el efecto. El resultado de "printf 'HelloWorld% d% d \ n' 1 2 3 4 5 6" probablemente lo aclara aún más. ¡Espero que esto ayude!
Adrian Petrescu
Veo. Es el comportamiento particular de printf lo que permite la repetición
GetFree
1
(Debo señalar que, desde un punto de vista puramente teórico, esta es probablemente la solución más rápida, ya que utiliza un único shell primitivo, no ningún proceso externo. En realidad, seamos sinceros, el rendimiento de los scripts de bash realmente no importa: )
Adrian Petrescu
1
Lo que es específico printfes que aplicará repetidamente argumentos en exceso a la cadena de formato, "bucleando" de forma gratuita. Por "exceso", quiero decir que hay más argumentos que %marcadores de posición.
Dennis Williamson
69

Aquí hay una forma anticuada que es bastante portátil:

yes "HelloWorld" | head -n 10

Esta es una versión más convencional de la respuesta de Adrian Petrescu usando la expansión de llaves:

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

Eso es equivalente a:

for i in 1 2 3 4 5

Esta es una versión un poco más concisa y dinámica de la respuesta de Pike :

printf -v spaces '%*s' 10 ''; printf '%s\n' ${spaces// /ten}
Dennis Williamson
fuente
¿Cómo deshacerse de las nuevas líneas al usar el comando yes?
GetFree
3
Una forma es canalizarlo sed -n 'H;${x;s/\n//gp}'u sed -n ':t;${s/\n//gp};N;bt'otra es hacer lo echo $(yes "HelloWorld" | head -n 10)que agrega un espacio entre cada copia de la cadena. Otra forma es canalizarlo, lo tr -d '\n'que también elimina la nueva línea final.
Dennis Williamson
2
Es como Haskell en un bash shell: Hashell?
wchargin
44
La solución sí es bastante ordenada
piggybox
La yessolución era exactamente lo que necesitaba, ya que quería duplicar un comando (cuya salida fluctúa). Por lo tanto:yes "$(my-command)" | head -n 2
Arnsholt
14

Esto se puede parametrizar y no requiere una variable temporal, FWIW:

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

O, si $Nes del tamaño de una matriz bash:

echo ${ARR[@]/*/blah}
twifkak
fuente
3
Esta es la solución POSIX 7 más corta que he visto hasta ahora seq, yesy {1..5}no son POSIX 7.
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
No debe mezclar datos en printfel especificador de formato. ¿Qué pasa si los datos contienen cadenas de formato? Esta es la forma correcta de especificar dinámicamente la "precisión" (longitud): printf '%*s' "$N"- habitúese a encerrar la cadena de formato entre comillas simples para evitar la expansión de variables allí.
Dennis Williamson
13

Algunas buenas maneras ya mencionadas. Sin seqembargo, no puedo olvidar lo bueno :

[john @ awesome] $ para i en `seq 5`; hacer eco "Hola"; hecho
Hola
Hola
Hola
Hola
Hola
John T
fuente
¡Este realmente respeta un cero, tratándolo como cero! (El {i..j}truco nunca devuelve un rango vacío.)
JellicleCat
10

Quizás otra forma que sea más general y útil para usted:

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

El bash shell es más poderoso de lo que la mayoría de la gente piensa :)

Adrian Petrescu
fuente
Esto obtiene mi voto, ya que es completamente interno; No se requiere bifurcación.
esm
2
¿A qué bifurcación te refieres? La respuesta original no requiere ninguno. La salida de 'type printf' es 'printf es un shell incorporado' y, por lo tanto, se ejecuta dentro del proceso bash original.
CodeGnome
Este es el único hasta el momento ( yes, printf, for i in {1..5}) que si el nes cero, devuelve una cadena vacía y sin existir estado de 1. También debido a la notación matemática para la comparación, es fácil haber compensado por 1 (por ejemplo, cambiando la <=que <)
Mehrad Mahmoudian
10

Puedes usar un truco. Hacer eco de una variable vacía no imprime nada. Entonces puedes escribir:

echo word$wojek{1..100}

Si $wojek1 $wojek2... $wojek100son variables no existentes, se repetirá su palabra 100 veces sin nada más.

Wojciech Waga
fuente
1
Es un truco feo y feo, y sin embargo no puedo evitar amarlo y usarlo.
16807
¡Quiéralo! Quizás usar en $_lugar de $wojekaclare la intención.
Mihai Todor
7

Repita los ntiempos, solo ponga n-1comas entre {}:

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

Repite 'helloworld' dos veces después del primer eco.

kev
fuente
55
Bien, pero ¿qué pasa si quiero obtener nde una variable?
GetFree
1
agrega un espacio extra después de cada 'helloworld'
PADYMKO
esto tampoco parece permitirle poner nuevas líneas en la cadena (es decir, obtener helloworld en sus propias líneas)
TankorSmash
5
awk 'BEGIN {while (c++<4) printf "Hello"}'

Resultado

Hola hola hola hola
Steven Penny
fuente
Use esto sin awk: while ((c ++ <5)); do printf 'hola'; hecho
fem
4

He experimentado advertencias de tuberías rotas con la yessolución, así que aquí hay otra buena alternativa:

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

basado en lo que @pike estaba insinuando

por cada caracter en string echo string

echo ${target//?/$replace}

Un ejemplo de un encabezado subrayado con =caracteres.

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

saldrá

ABCDEF
======

Esto parece tener un puerto entre Linux y OS X y eso me hace feliz.

nJoy!

nickl-
fuente
3

Si estás en BSD, puedes usarlo seq.

$ seq -f "Hello, world" 5
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Qix
fuente
1
En seq (GNU coreutils) 8.25, esto da seq: format 'Hello, world' has no % directive, obligando a una directiva de formato a estar presente. GNU coreutils se utilizan, por ejemplo, en muchas distribuciones de Linux y Cygwin. Incluyendo la información aquí para aquellos que faltan la información de que solo funciona en BSD seq.
Palec
2
line="==========================="
line=${line:0:10}
${line//"="/"ten "}

salidas

ten ten ten ten ten ten ten ten ten ten
Pico común
fuente
Quizás un ejemplo más detallado: declare c = '-----'; c = $ {c // $ {c: 0: 1} / $ c}; echo $ c # Imprime "-" 25 veces.
Stephen Niedzielski
2

Suponiendo que desea algo como el xoperador de Perl , donde no obtiene automáticamente una nueva línea entre repeticiones:

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

Explícitamente utilicé un forbucle porque no puedes escribir {1..$n}en bash: la expansión de llaves se realiza antes de la sustitución de variables.

Glenn Jackman
fuente
2

No está exactamente integrado en Linux, pero si tienes Python instalado ...

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

O en una línea, como sugirió el comentarista:

python -c 'print "This is a test.\n" * 10'
eqzx
fuente
44
En realidad no es tan útil, ya que no se puede integrar fácilmente en los scripts de shell, etc. Y dado que hay alrededor de mil millones de formas de hacer esto en el propio shell, veo pocas razones para sacar las armas grandes (es decir, Python). .
Adrian Petrescu
77
Estoy de acuerdo con su segundo punto, pero no con el puño ... es fácil de integrar en un script de shell: python -c 'print "Esta es una prueba. \ N" * 10'
larsks
Me gusta la legibilidad de esta solución, una buena razón para mí. ;)
elias
2

No hay magia aquí:

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

brablc
fuente
1

Prueba este:

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

Creará (cien guiones):


Alle Aldine
fuente