Respuestas:
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.
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
Da
foo=================
${#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í
filler=$( jot -s '' -c 16 '=' '=' )
(para 16 =
en una línea). Los sistemas GNU pueden usar seq
:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
Otros sistemas pueden usar Perl o alguna otra forma más rápida de crear la cadena dinámicamente.
printf
para generar el filtro que está casi disponible en todos los sistemas y la expansión de la llave con los cascos bash/szh
?
printf
+ expansión de llaves bash
?
printf "%.20s:\n\n" "$str========================="
donde %.20s
está el formato de truncamiento de cadena
Una forma de hacerlo:
printf "====================:\r%s\n\n" 'hello world!!'
====================\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 que echo
, por muchas razones.
Un enfoque de Perl:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
O, mejor, @SatoKatsura señaló en los comentarios:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Si necesita admitir caracteres UTF de varios bytes, use:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
La misma idea en el shell:
v='hello world!!'; while [ ${#v} -lt 20 ]; do v="$v""="; done; printf '%s\n\n' "$v"
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 lado perl6
es molesto de muchas maneras.
PERL_UNICODE='AS'
. Por ejemplo: printf '%s' nóóös | perl -nle 'print length($_)'
imprime 8 ("incorrecto") mientras printf '%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 primero Shell 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.
printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:
Explicaciones:
Normalmente, como Brace Expansion , Shell se expande de la {1..20}
siguiente manera si imprimimos esos.
printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Entonces, al agregarle un signo igual ={1..20}
, Shell se expandirá de la siguiente manera.
printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20
Y con lo printf '%.1s'
que realmente significa printf '%WIDE.LENGTH'
, estamos imprimiendo solo una LONGITUD de las anteriores con 1
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.