Antworten:
Aktualisierte Antwort, um allgemeinere Lösung zu sein. siehe auch meine andere antwort unten mit nur shell brace expansion und pritnf
.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
Wie es funktioniert?
dies (=*):$/
fängt ein Leerzeichen ein, eines oder mehrere =
, gefolgt von einem Doppelpunkt :
am Ende seiner Eingabe; Wir machen das Set =
als Gruppen-Match und \1
werden seine Rückverweisung sein.
Mit :loop
definierten wir ein Label mit dem Namen loop
und mit t loop
ihm zu diesem Label springen , wenn eine s/ (=*):$/\1=:/
erfolgreiche Substitution getan hat;
Im Ersatzteil mit \1=:
wird immer die Anzahl von =
s erhöht und der Doppelpunkt selbst bis zum Ende der Zeichenfolge zurückgesetzt.
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
Gibt
foo=================
${#string}
ist die Länge des Werts $string
und ${filler:${#string}}
die Teilzeichenfolge $filler
von Offset ${#string}
an.
Die Gesamtbreite der Ausgabe entspricht der maximalen Breite von $filler
oder $string
.
Der Füllstring kann auf Systemen, jot
die dynamisch erstellt wurden, mithilfe von erstellt werden
filler=$( jot -s '' -c 16 '=' '=' )
(für 16 =
in einer Zeile). GNU-Systeme können verwenden seq
:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
Andere Systeme verwenden möglicherweise Perl oder eine andere schnellere Methode, um die Zeichenfolge dynamisch zu erstellen.
printf
dem Filter, der in fast allen Systemen verfügbar ist, und der Klammererweiterung mit den Schalen wie erzeugen bash/szh
?
printf
+ geschweiften Erweiterungen machen bash
?
printf "%.20s:\n\n" "$str========================="
Wo %.20s
ist das Format für das Abschneiden von Zeichenfolgen?
Ein Weg, es zu tun:
printf "====================:\r%s\n\n" 'hello world!!'
====================\rhello world
, was ein Problem sein kann, wenn das OP dies speichern und nicht nur auf dem Bildschirm drucken muss.
echo -e '=================\rHello World!!'
, aber hat das gleiche Problem wie @terdon darauf hingewiesen.
echo
unterstützt -e
. printf
ist echo
aus vielen Gründen fast immer besser als .
Ein Perl-Ansatz:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
Oder besser gesagt, @SatoKatsura hat in den Kommentaren darauf hingewiesen:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Wenn Sie UTF-Multibyte-Zeichen unterstützen müssen, verwenden Sie:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Gleiche Idee in der 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"'
. Dieses (und alle anderen bisher veröffentlichten Lösungen) funktioniert jedoch nicht, wenn Mehrbyte-Zeichen beteiligt sind.
perl6
könnte eine Möglichkeit geben, dies auch mit Multibyte-Zeichen korrekt zu tun. Aber andererseits perl6
ist es in vielerlei Hinsicht ärgerlich.
PERL_UNICODE='AS'
. Zum Beispiel: printf '%s' nóóös | perl -nle 'print length($_)'
druckt 8 ( "falsch") , während printf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'
druckt 5 ( "richtigen").
Eine andere Möglichkeit besteht darin, nur den printf
Befehl zu verwenden und das Zeichenauffüllmuster zu generieren, indem Shell Brace Expansion
Sie zuerst (Sie können mit einer Zahl ≥ den zu druckenden Formatierungsbereich beenden{1..end}
) und nur jedes erste Zeichen davon abrufen, %.1s
das =
s ist, und dann nur die ersten 20 Zeichen drucken Bereich davon %.20s
. Dies ist eine bessere Möglichkeit, Zeichen / Wörter zu wiederholen, anstatt sie zu duplizieren.
printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:
Erklärungen:
Normalerweise als Klammererweiterung , Shellerweiterung {1..20}
wie folgt, wenn wir diese drucken.
printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Wenn Sie ein Gleichheitszeichen hinzufügen ={1..20}
, wird die Shell folgendermaßen erweitert.
printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20
Und printf '%.1s'
womit ist eigentlich gemeint printf '%WIDE.LENGTH'
, wir drucken nur eine LÄNGE der oben genannten mit der Standardeinstellung 1
WIDE . so wird es =
nur s geben und sich 20 mal wiederholen.
Jetzt printf '%.20s:\n'
drucken wir nur die Länge 20 von $str
und wenn die Länge $str
<20 ist, wird der Rest von den generierten =
s zum Füllen anstelle von Leerzeichen benötigt.