2011-04-27 38 views

Respuesta

29

seguro, sólo tiene que utilizar printf y un poco de manipulación de cadenas fiesta

$ s=$(printf "%-30s" "*") 
$ echo "${s// /*}" 
****************************** 

Debe haber un camino más corto, pero en la actualidad que es cómo lo haría. Usted puede hacer esto en una función que se puede almacenar en una biblioteca para uso futuro

printf_new() { 
str=$1 
num=$2 
v=$(printf "%-${num}s" "$str") 
echo "${v// /*}" 
} 

Prueba de funcionamiento:

$ printf_new "*" 20 
******************** 
$ printf_new "*" 10 
********** 
$ printf_new "%" 10 
%%%%%%%%%% 
+2

Puede evitar la subshell aquí si usa 'printf -v'. 'printf -v str '% -30s' ''; echo "$ {str ///*}" ' – kojiro

+1

-1. Esto es muy lento, especialmente para> 1000 caracteres. Casi todo es más rápido, incluyendo 'printf '% .s *' {1..30}', o 'printf '% * s' 1000000 '' | tr '' '*'' para números grandes. – Deadcode

+1

Printf_new falla en la tercera ejecución de prueba. Lo arreglaría así: 'printf -v v"% - * s "" $ num "" "; echo "$ {v ///$ str}" ' – jarno

2

Es feo, pero se puede hacer así:

$ for a in `seq 5`; do echo -n %; done 
%%%%% 

Por supuesto, seq es un profesional externo gramo (que probablemente tengas).

+2

¿Por qué utilizar otro programa cuando simplemente puede escribir: 'para a en {1..5}; hacer eco -n%; done'.) –

+1

Me di cuenta de que en un script, mi "solución" no funciona, aquí hay una solución. –

+0

-1. Es más lento que 'printf"% 0.s %% "{1..5}', que a su vez es más lento que 'printf '% * s' 5 '' | tr '' '%''. – Deadcode

7

me gusta esto:

echo $(yes % | head -n3) 

Es posible que no desea:

for ((i=0; i<3; i++)){ 
    echo -ne "%" 
} 

Es posible que como este:

s=$(printf "%3s"); echo " ${s// /%}" 

Fuente: http://dbaspot.com/shell/357767-bash-fast-way-repeat-string.html

También hay esta la forma, pero no es muy útil:

echo %{,,} 
+5

+1 para la combinación de 'sí' y' cabeza' – fmark

+0

¡Eso es lo que usan ahora! Salí buscando '/ dev/y' y no pude encontrarlo en mi sistema moderno. –

0

Otra:

char='%' 
count=5 
result=$(printf "%${count}s" ' ') 
echo -e ${result// /$char} 
1
  1. Es posible para obtener cualquier número de carácter cero (\0) de /dev/zero. Lo único que queda por hacer es

    head -c 20 /dev/zero |tr '\0' '+' 
    

    Tenga en cuenta que head y tr son comandos externos. Para que se invoque en un proceso separado.

  2. Es posible "optimizar" esta solución con caché de cadenas.

    CACHE="$(head -c 1000 /dev/zero |tr '\0' '+')" 
    echo "${CACHE:0:10}" 
    echo "${CACHE:0:100}" 
    echo "${CACHE:0:300}" 
    

    Sólo hay bash empotrados en el estado de eco. Entonces, podemos usarlo en ciclo.

+1

Esto no funciona; entra en un bucle sin fin que da salida a un número ilimitado de caracteres, no a 20 según lo previsto. El comando correcto es 'head -c 20/dev/zero | tr '\ 0' '+''. – Deadcode

+0

Esto parece ser un error tipográfico en la parte de ssvda. Debería ser 'head -c 20' para imprimir los primeros 20 caracteres. 'head -n 20' muestra las primeras 20 líneas. – Six

89

De hecho, hay una sola línea que puede hacer esto:

printf "%0.s-" {1..10} 

impresiones

---------- 

Aquí está el desglose de los argumentos que se pasan a printf:

  • % s - Esto especifica una cadena de cualquier longitud
  • % 0s - Especifica una cadena de longitud cero, pero si el argumento es más largo se imprimirá todo el asunto
  • % 0.s - Este es el mismo que el anterior, pero el período dice printf para truncar la cadena si es más largo que la longitud especificada, que es cero
  • {1..10} - Esta es una expansión de llave que realmente pasa los argumentos "1 2 3 4 5 6 7 8 9 10"
  • "-" - Este es un carácter adicional proporcionado a printf, podría ser cualquier cosa (para un "%" debe evitarlo con otro "%" primero, es decir, "%%")
  • Por último, el comportamiento predeterminado para printf si darle más argumentos de los que se especifican en el formato cadena es volver al principio de la cadena de formato y ejecutarlo de nuevo.

El resultado final de lo que está pasando aquí, entonces, es que usted está diciendo printf que desea que se imprima una cadena de longitud cero sin caracteres adicionales si la cadena entregada es más largo que cero. Luego, después de esta cadena de longitud cero, imprima un "-" (o cualquier otro conjunto de caracteres). Luego le proporciona 10 argumentos, por lo que imprime 10 cadenas de longitud cero, cada una con un "-".

¡Es un trazador de líneas único que imprime cualquier número de caracteres que se repiten!

Editar:

Casualmente, si desea imprimir $variable caracteres sólo hay que cambiar el argumento ligeramente para utilizar seq en lugar de la expansión de llaves de la siguiente manera:

printf '%0.s-' $(seq 1 $variable) 

Esto en cambio pasar argumentos " 1 2 3 4 ... $ variable "a printf, imprimiendo con precisión $variable instancias de" - "

+4

Muy bien, pero esto no funciona en *** #!/Bin/sh *** pero solo en *** #!/Bin/bash *** –

+0

Dado que esto usa un bash incorporado, para un pequeño número de los caracteres repetidos deberían ser más rápidos que los métodos que generan los procesos externos. Para números grandes, 'printf '% * s' 1000000 '' | tr '' '' '' y otros métodos son más rápidos. – Deadcode

+0

Mi única pregunta es en qué situación te gustaría imprimir un personaje que se repite 1 millón de veces? Podrían ver otras operaciones, pero eso solo saturaría tu salida con personajes aparentemente sin sentido. – CaffeineConnoisseur

-1

Aquí está la manera más simple de hacerlo

seq -s % 4|tr -d '[:digit:]' 

en cuenta que habrá sólo un 3 '%' en la secuencia creada.

+0

-1. Imprime una nueva línea principal, imprime un carácter menos que el número pasado, y es más lento que 'printf '% * s' 3 '' | tr '' '%''. – Deadcode

15

La respuesta actual aceptada para esta pregunta (por ghostdog74) proporciona un método que se ejecuta muy lentamente incluso para un número moderadamente alto de caracteres. La respuesta más votados (por CaffeineConnoisseur) es mejor, pero aún es bastante lenta.

Esto es lo que, en mis pruebas, ha ejecutado más rápido de todos (incluso más rápido que la versión de Python):

perl -E "print '*' x 1000" 

En segundo lugar se ubicó el comando python:

python -c "print('*' * 1000)" 

Si ninguno perl y python están disponibles, entonces este es el tercero mejor:

head -c 1000 /dev/zero | tr '\0' '*' 

Y en cuarto lugar está el que u cantar la fiesta de printf incorporada junto con tr:

printf '%*s' 1000 | tr ' ' '*' 

Y aquí está uno (de CaffeineConnoisseur 's respuesta) que está en el quinto lugar en la velocidad para un gran número de caracteres repetidos, pero podría ser más rápido para los números pequeños (debido a usar solamente una fiesta incorporado, y no generando un proceso externo):

printf '%.s*' {1..1000} 
+0

Suponiendo que '*' es el carácter que se está imprimiendo, ¿cuál es el propósito del '% .s' anterior en el ejemplo final? – Hashim

+0

"% s" es una especificación de formato para printf, que simplemente significa cadena. Entre "%" y "s", puede establecer atributos de longitud para la cadena. Usando cualquiera "." o ".0" establecerá la longitud máxima de la cadena en cero, imprimiendo nada para esa cadena. En este ejemplo, el rango se expande a 1 2 3 4 5 ..... 98 99 100 y cada número se trata como una cadena de longitud cero. Esta es la forma de controlar el recuento de asteriscos impresos. –

0
#!/usr/bin/awk -f 
BEGIN { 
    while (c++ < 3) printf "%" 
} 

Resultado

 
%%% 
Cuestiones relacionadas