Respuesta actualizada para ser una solución más general. vea también mi otra respuesta a continuación usando solo expansión de llave de concha y pritnf
.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
¿Cómo funciona?
esto (=*):$/
captura un espacio, uno o más =
que seguido de dos puntos :
al final de su entrada; hacemos que el conjunto =
sea una coincidencia grupal y \1
será su referencia de referencia.
Con :loop
definimos una etiqueta llamada loop
y con t loop
ella saltaremos a esa etiqueta cuando a s/ (=*):$/\1=:/
haya realizado una sustitución exitosa;
En la parte de reemplazo con \1=:
, siempre incrementará el número de =
sy retrocederá los dos puntos hasta el final de la cadena.
Da
${#string}
es la longitud del valor$string
y${filler:${#string}}
es la subcadena de$filler
desde el desplazamiento${#string}
hacia adelante.El ancho total de la salida será el ancho máximo de
$filler
o$string
.La cadena de relleno se
jot
puede crear dinámicamente en sistemas que sí(para 16
=
en una línea). Los sistemas GNU pueden usarseq
:Otros sistemas pueden usar Perl o alguna otra forma más rápida de crear la cadena dinámicamente.
fuente
printf
para generar el filtro que está casi disponible en todos los sistemas y la expansión de la llave con los cascosbash/szh
?printf
+ expansión de llavesbash
?donde
%.20s
está el formato de truncamiento de cadenafuente
Una forma de hacerlo:
fuente
====================\rhello world
, lo que podría ser un problema si el OP necesita almacenar esto y no solo imprimirlo en la pantalla.echo -e '=================\rHello World!!'
, pero tiene el mismo problema que @terdon señaló que.echo
compatible-e
.printf
Casi siempre es mejor queecho
, por muchas razones.Un enfoque de Perl:
O, mejor, @SatoKatsura señaló en los comentarios:
Si necesita admitir caracteres UTF de varios bytes, use:
La misma idea en el shell:
fuente
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
. Sin embargo, esta (y todas las otras soluciones publicadas hasta el momento) se rompe si hay caracteres de varios bytes involucrados.perl6
podría tener una manera de hacerlo correctamente incluso con caracteres de varios bytes. Pero por otro ladoperl6
es molesto de muchas maneras.PERL_UNICODE='AS'
. Por ejemplo:printf '%s' nóóös | perl -nle 'print length($_)'
imprime 8 ("incorrecto") mientrasprintf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'
imprime 5 ("correcto").Otra forma es usar solo el
printf
comando y generar el patrón de relleno de caracteres primeroShell Brace Expansion
(puede poner el final con un área de formato de número ≥ en la que desea imprimir{1..end}
) y obtener solo cada primer carácter%.1s
que sea=
sy luego imprimir solo los primeros 20 caracteres de longitud área de eso%.20s
. Esta es una forma mejor de repetir caracteres / palabras en lugar de duplicarlos.Explicaciones:
Normalmente, como Brace Expansion , Shell se expande de la
{1..20}
siguiente manera si imprimimos esos.Entonces, al agregarle un signo igual
={1..20}
, Shell se expandirá de la siguiente manera.Y con lo
printf '%.1s'
que realmente significaprintf '%WIDE.LENGTH'
, estamos imprimiendo solo una LONGITUD de las anteriores con1
ANCHO predeterminado . así resultará=
s solamente y se repetirá 20 veces.Ahora con
printf '%.20s:\n'
estamos imprimiendo solo la longitud de 20$str
y si la longitud de$str
<20, el resto tomará de=
s generados para rellenar en lugar de espacios.fuente