Réponses:
Réponse mise à jour pour être une solution plus générale. voir aussi ma autre réponse ci-dessous en utilisant uniquement l'expansion de l'accolade shell et pritnf
.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
Comment ça fonctionne?
cela (=*):$/
capture un espace, un ou plusieurs =
qui a suivi par deux points :
à la fin de son entrée; nous faisons l'ensemble de =
comme match de groupe et \1
serons sa référence arrière.
Avec, :loop
nous avons défini une étiquette nommée loop
et avec t loop
elle, nous passerons à cette étiquette lorsque a s/ (=*):$/\1=:/
a réussi la substitution;
En pièce de rechange avec \1=:
, il incrémentera toujours le nombre de =
s et remettra les deux points à la fin de la chaîne.
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
Donne
foo=================
${#string}
est la longueur de la valeur $string
et ${filler:${#string}}
est la sous-chaîne de à $filler
partir du décalage ${#string}
.
La largeur totale de la sortie sera celle de la largeur maximale de $filler
ou $string
.
La chaîne de remplissage peut, sur les systèmes existants jot
, être créée dynamiquement à l'aide de
filler=$( jot -s '' -c 16 '=' '=' )
(pour 16 =
en ligne). Les systèmes GNU peuvent utiliser seq
:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
D'autres systèmes peuvent utiliser Perl ou un autre moyen plus rapide de créer dynamiquement la chaîne.
printf
pour générer le filtre qui est presque disponible dans tous les systèmes et l'expansion de l'entretoise avec les coques comme bash/szh
?
printf
extension + brace en bash
?
printf "%.20s:\n\n" "$str========================="
où %.20s
est le format de chaîne tronquée
Une façon de le faire:
printf "====================:\r%s\n\n" 'hello world!!'
====================\rhello world
, ce qui pourrait être un problème si l'OP doit le stocker et pas seulement l'imprimer à l'écran.
echo -e '=================\rHello World!!'
, mais a le même problème que @terdon l'a souligné.
echo
supports -e
. printf
est presque toujours mieux que echo
, pour de nombreuses raisons.
Une approche Perl:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
Ou mieux, @SatoKatsura a souligné dans les commentaires:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Si vous devez prendre en charge les caractères multi-octets UTF, utilisez:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Même idée dans le 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"'
. Cependant, cela (et toutes les autres solutions publiées jusqu'à présent) s'arrête si des caractères multi-octets sont impliqués.
perl6
pourrait avoir un moyen de le faire correctement, même avec des caractères multi-octets. Mais d'un autre côté, perl6
c'est ennuyeux à bien des égards.
PERL_UNICODE='AS'
. Par exemple: printf '%s' nóóös | perl -nle 'print length($_)'
imprime 8 ("faux") tandis que printf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'
imprime 5 ("correct").
Une autre façon consiste à utiliser uniquement la printf
commande et à générer d'abord le motif de remplissage des caractères par Shell Brace Expansion
(vous pouvez mettre fin avec un nombre ≥ zone de formatage dans laquelle vous souhaitez imprimer {1..end}
) et à n'en obtenir que chaque premier caractère, %.1s
qui est =
s, puis à n'imprimer que les 20 premiers caractères domaine de cela %.20s
. C'est en quelque sorte une meilleure façon d'avoir des caractères / mots répétés au lieu de les dupliquer.
printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:
Explications:
Normalement, en tant qu'expansion Brace , le shell se développe {1..20}
comme suit si nous les imprimons.
printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Ainsi, en y ajoutant un signe égal ={1..20}
, le shell se développera comme suit.
printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20
Et printf '%.1s'
ce qui signifie en fait printf '%WIDE.LENGTH'
, nous n'imprimons qu'une seule LONGUEUR de ceux ci-dessus avec 1
WIDE par défaut . il en résultera =
seulement s et 20 fois répété.
Maintenant, avec printf '%.20s:\n'
nous n'imprimons que la longueur de 20 $str
et si la longueur est $str
<20, le reste prendra des =
s générés à remplir au lieu d'espaces.