Sie können externe Dienstprogramme aufrufen (siehe andere Antworten), aber dadurch wird Ihr Skript langsamer, und es ist schwierig, die Installation richtig zu machen.
Zsh
In zsh können Sie schreiben ${#$(readlink -f /etc/fstab)}
, um die Länge der Befehlsersetzung zu ermitteln. Beachten Sie, dass dies nicht die Länge der Befehlsausgabe ist, sondern die Länge der Ausgabe ohne nachgestellte Zeilenumbruch.
Wenn Sie die genaue Länge der Ausgabe wünschen, geben Sie am Ende ein zusätzliches Zeichen ohne Zeilenumbruch aus und subtrahieren Sie eines.
$((${#$(readlink -f /etc/fstab; echo .)} - 1))
Wenn Sie die Nutzlast in der Ausgabe des Befehls wünschen, müssen Sie hier zwei subtrahieren , da die Ausgabe von readlink -f
der kanonische Pfad plus eine neue Zeile ist.
$((${#$(readlink -f /etc/fstab; echo .)} - 2))
Dies unterscheidet sich von ${#$(readlink -f /etc/fstab)}
dem seltenen, aber möglichen Fall, in dem der kanonische Pfad selbst in einer neuen Zeile endet.
Für dieses spezielle Beispiel benötigen Sie überhaupt kein externes Dienstprogramm, da zsh über ein integriertes Konstrukt verfügt, das readlink -f
über den Verlaufsmodifikator äquivalent ist A
.
echo /etc/fstab(:A)
Verwenden Sie den Verlaufsmodifikator in einer Parametererweiterung, um die Länge zu ermitteln:
${#${:-/etc/fstab}:A}
Wenn Sie den Dateinamen in einer Variablen filename
haben, wäre das ${#filename:A}
.
Muscheln im Bourne / POSIX-Stil
Keine der reinen Bourne / POSIX-Shells (Bourne, Ash, Mksh, Ksh93, Bash, Yash…) hat eine ähnliche Erweiterung, die ich kenne. Wenn Sie eine Parametersubstitution auf die Ausgabe einer Befehlssubstitution anwenden oder Parametersubstitutionen verschachteln müssen, verwenden Sie aufeinanderfolgende Stufen.
Sie können die Verarbeitung in eine Funktion einfügen, wenn Sie möchten.
command_output_length_sans_trailing_newlines () {
set -- "$("$@")"
echo "${#1}"
}
oder
command_output_length () {
set -- "$("$@"; echo .)"
echo "$((${#1} - 1))"
}
aber es gibt normalerweise keinen Nutzen; Mit Ausnahme von ksh93 kann ein zusätzlicher Fork die Ausgabe der Funktion verwenden, sodass Ihr Skript langsamer wird und es selten Vorteile für die Lesbarkeit gibt.
Die Ausgabe von readlink -f
ist wiederum der kanonische Pfad plus eine neue Zeile; Wenn Sie die Länge des kanonischen Pfades möchten, subtrahieren Sie 2 statt 1 Zoll command_output_length
. Die Verwendung command_output_length_sans_trailing_newlines
liefert nur dann das richtige Ergebnis, wenn der kanonische Pfad selbst nicht in einer neuen Zeile endet.
Bytes gegen Zeichen
${#…}
soll die Länge in Zeichen sein, nicht in Bytes, was bei Multibyte-Gebietsschemas einen Unterschied macht. Ziemlich aktuelle Versionen von ksh93, bash und zsh berechnen die Länge in Zeichen gemäß dem Wert von LC_CTYPE
zum Zeitpunkt der ${#…}
Erweiterung des Konstrukts. Viele andere gängige Shells unterstützen Multibyte-Gebietsschemas nicht wirklich: Ab Strich 0.5.7 geben mksh 46 und posh 0.12.3 ${#…}
die Länge in Bytes zurück. Wenn Sie die Länge in Zeichen zuverlässig festlegen möchten, verwenden Sie das wc
Dienstprogramm:
$(readlink -f /etc/fstab | wc -m)
Solange $LC_CTYPE
ein gültiges Gebietsschema festgelegt ist, können Sie sicher sein, dass dies entweder fehlerhaft ist (auf einer alten oder eingeschränkten Plattform, die keine Multibyte-Gebietsschemas unterstützt) oder die richtige Länge in Zeichen zurückgibt. (Für Unicode bedeutet "Länge in Zeichen" die Anzahl der Codepunkte - die Anzahl der Glyphen ist aufgrund von Komplikationen wie dem Kombinieren von Zeichen eine weitere Geschichte.)
Wenn Sie die Länge in Bytes möchten, legen Sie diese LC_CTYPE=C
vorübergehend fest oder verwenden Sie wc -c
stattdessen wc -m
.
Das Zählen von Bytes oder Zeichen mit wc
schließt alle nachfolgenden Zeilenumbrüche aus dem Befehl ein. Wenn Sie die Länge des kanonischen Pfads in Bytes angeben möchten, ist dies der Fall
$(($(readlink -f /etc/fstab | wc -c) - 1))
Subtrahieren Sie 2, um es in Zeichen zu erhalten.
readlink -f /etc/fstab
ist 11 Zeichen. Vergessen Sie nicht die Newline. Andernfalls würden Sie sehen,/etc/fstabluser@cern:~$
wann Sie es von einer Shell ausgeführt haben.