Risposte:
Risposta aggiornata per essere una soluzione più generale. vedi anche la mia altra risposta di seguito usando solo l'espansione delle parentesi graffe e pritnf.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
Come funziona?
questo (=*):$/cattura uno spazio, uno o più =che è seguito da due punti :alla fine del suo input; facciamo l'insieme di =come una partita di gruppo e \1sarà il suo riferimento indietro.
Con :loopabbiamo definito un'etichetta denominata loope con t loopessa salterà a quell'etichetta quando una s/ (=*):$/\1=:/sostituzione ha avuto esito positivo;
Nella parte di ricambio con \1=:, incrementa sempre il numero di se =riporta i due punti alla fine della stringa.
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
dà
foo=================
${#string}è la lunghezza del valore $stringed ${filler:${#string}}è la sottostringa $fillerdell'offset in ${#string}avanti.
La larghezza totale dell'output sarà quella della larghezza massima di $fillero $string.
La stringa di riempimento può, sui sistemi che ha jot, essere creata in modo dinamico utilizzando
filler=$( jot -s '' -c 16 '=' '=' )
(per 16 =in una riga). I sistemi GNU possono usare seq:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
Altri sistemi possono usare il Perl o qualche altro modo più veloce per creare dinamicamente la stringa.
printfper generare il filtro che è quasi disponibile in tutti i sistemi e l'espansione del controvento con le shell come bash/szh?
printfespansione + parentesi graffa bash?
printf "%.20s:\n\n" "$str========================="
dove %.20sè il formato di troncamento della stringa
Un modo per farlo:
printf "====================:\r%s\n\n" 'hello world!!'
====================\rhello world, il che potrebbe essere un problema se l'OP deve memorizzarlo e non stamparlo solo sullo schermo.
echo -e '=================\rHello World!!', ma ha lo stesso problema che ha sottolineato @terdon.
echosupporta -e. printfè quasi sempre meglio di echo, per molte ragioni.
Un approccio Perl:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
O meglio, @SatoKatsura ha sottolineato nei commenti:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Se è necessario supportare caratteri multi-byte UTF, utilizzare:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Stessa idea nella 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"'. Tuttavia, questa (e tutte le altre soluzioni pubblicate finora) si interrompe se sono coinvolti caratteri multibyte.
perl6potrebbe avere un modo per farlo correttamente anche con caratteri multi-byte. Ma d'altra parte perl6è fastidioso in molti modi.
PERL_UNICODE='AS'. Ad esempio: printf '%s' nóóös | perl -nle 'print length($_)'stampa 8 ("errato") mentre printf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'stampa 5 ("corretto").
Un altro modo è usare solo il printfcomando e generare prima il motivo di riempimento dei caratteri per Shell Brace Expansion(È possibile terminare con un numero ≥ area di formattazione in cui si desidera stampare {1..end}) e ottenere solo ogni primo carattere di esso %.1sche è se =quindi stampare solo i primi 20 caratteri di lunghezza area di quello %.20s. Questo è un modo migliore per avere caratteri / parole ripetuti invece di duplicarli.
printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:
spiegazioni:
Normalmente come Brace Expansion , la shell si espande {1..20}come segue se le stampiamo.
printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Quindi con l'aggiunta di un segno uguale ad esso ={1..20}, la shell si espanderà come segue.
printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20
E con ciò printf '%.1s'che in realtà significa printf '%WIDE.LENGTH', stiamo stampando solo una LUNGHEZZA di quelle sopra con 1 WIDE predefinito . così risulterà =solo e 20 volte ripetuto.
Ora con printf '%.20s:\n'stiamo stampando solo la lunghezza di 20 $stre se la lunghezza è $str<20, il resto richiederà da =s generati da riempire invece di spazi.