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?


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

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}

¿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}

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

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


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.


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.


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

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

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!


3

Si estás en BSD, puedes usarlo seq.

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

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

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.


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'

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


1

Prueba este:

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

Creará (cien guiones):


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.