Resposta atualizada para ser uma solução mais geral. veja também minha outra resposta abaixo usando apenas shell brace expansion e pritnf
.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
Como funciona?
isso (=*):$/
captura um espaço, um ou mais =
que é seguido por dois pontos :
no final de sua entrada; fazemos o conjunto =
como uma correspondência de grupo e \1
será sua referência anterior.
Com :loop
nós definimos um rótulo nomeado loop
e com t loop
ele pularemos para esse rótulo quando um s/ (=*):$/\1=:/
fizer uma substituição bem-sucedida;
Em substituição a \1=:
, sempre aumentará o número de se =
retornará os dois pontos até o final da string.
Dá
${#string}
é o comprimento do valor$string
e${filler:${#string}}
é a substring$filler
do deslocamento em${#string}
diante.A largura total da saída será a largura máxima de
$filler
ou$string
.A cadeia de preenchimento pode, em sistemas que possui
jot
, ser criada dinamicamente usando(para 16
=
em uma linha). Os sistemas GNU podem usarseq
:Outros sistemas podem usar Perl ou alguma outra maneira mais rápida de criar a string dinamicamente.
fonte
printf
para gerar o filtro que está quase disponível em todos os sistemas e a expansão de braçadeiras com cascas comobash/szh
?printf
expansão + bracebash
?onde
%.20s
é o formato de truncamento de stringfonte
Uma maneira de fazer isso:
fonte
====================\rhello world
, o que pode ser um problema se o OP precisar armazenar isso e não apenas imprimi-lo na tela.echo -e '=================\rHello World!!'
, mas tem o mesmo problema que o @terdon apontou isso.echo
suporte-e
.printf
quase sempre é melhor queecho
, por muitas razões.Uma abordagem Perl:
Ou melhor, @SatoKatsura apontou nos comentários:
Se você precisar oferecer suporte a caracteres de vários bytes UTF, use:
Mesma idéia no shell:
fonte
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
. No entanto, essa (e todas as outras soluções postadas até o momento) são interrompidas se caracteres de vários bytes estiverem envolvidos.perl6
pode ter uma maneira de fazê-lo corretamente, mesmo com caracteres de vários bytes. Mas, por outro lado,perl6
é irritante de muitas maneiras.PERL_UNICODE='AS'
. Por exemplo:printf '%s' nóóös | perl -nle 'print length($_)'
imprime 8 ("incorreto") enquantoprintf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'
imprime 5 ("correto").Outra maneira é usar apenas o
printf
comando e gerar primeiro o padrão de preenchimento de caracteresShell Brace Expansion
(Você pode finalizar com um número ≥ da área de formatação em que deseja imprimir{1..end}
) e obter apenas cada primeiro caractere%.1s
que seja=
s e depois imprimir apenas os primeiros 20 caracteres área disso%.20s
. Essa é a maneira melhor de repetir caracteres / palavra em vez de duplicá-los.Explicações:
Normalmente, como expansão de chaves , expansão de shell da
{1..20}
seguinte forma, se as imprimirmos.Portanto, com a adição de um sinal de igual
={1..20}
, o shell se expandirá da seguinte forma.E com o
printf '%.1s'
que realmente significaprintf '%WIDE.LENGTH'
, estamos imprimindo apenas um COMPRIMENTO daqueles acima com o padrão1
WIDE . assim resultará=
apenas se 20 vezes se repetiu.Agora, com
printf '%.20s:\n'
estamos imprimindo apenas o comprimento de 20$str
e se o comprimento for$str
<20, o restante levará de=
s gerados para preencher em vez de espaços.fonte