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.
Gibt
${#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(für 16
=
in einer Zeile). GNU-Systeme können verwendenseq
:Andere Systeme verwenden möglicherweise Perl oder eine andere schnellere Methode, um die Zeichenfolge dynamisch zu erstellen.
quelle
printf
dem Filter, der in fast allen Systemen verfügbar ist, und der Klammererweiterung mit den Schalen wie erzeugenbash/szh
?printf
+ geschweiften Erweiterungen machenbash
?Wo
%.20s
ist das Format für das Abschneiden von Zeichenfolgen?quelle
Ein Weg, es zu tun:
quelle
====================\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
istecho
aus vielen Gründen fast immer besser als .Ein Perl-Ansatz:
Oder besser gesagt, @SatoKatsura hat in den Kommentaren darauf hingewiesen:
Wenn Sie UTF-Multibyte-Zeichen unterstützen müssen, verwenden Sie:
Gleiche Idee in der Shell:
quelle
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 andererseitsperl6
ist es in vielerlei Hinsicht ärgerlich.PERL_UNICODE='AS'
. Zum Beispiel:printf '%s' nóóös | perl -nle 'print length($_)'
druckt 8 ( "falsch") , währendprintf '%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, indemShell 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.Erklärungen:
Normalerweise als Klammererweiterung , Shellerweiterung
{1..20}
wie folgt, wenn wir diese drucken.Wenn Sie ein Gleichheitszeichen hinzufügen
={1..20}
, wird die Shell folgendermaßen erweitert.Und
printf '%.1s'
womit ist eigentlich gemeintprintf '%WIDE.LENGTH'
, wir drucken nur eine LÄNGE der oben genannten mit der Standardeinstellung1
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.quelle