Możesz wywoływać narzędzia zewnętrzne (zobacz inne odpowiedzi), ale spowalniają one twój skrypt i ciężko jest uzyskać prawidłową instalację wodociągową.
Zsh
W zsh możesz pisać, ${#$(readlink -f /etc/fstab)}
aby uzyskać długość podstawienia polecenia. Zauważ, że nie jest to długość danych wyjściowych polecenia, to długość danych wyjściowych bez końcowego znaku nowej linii.
Jeśli potrzebujesz dokładnej długości wyniku, wypisz dodatkowy znak nie będący znakiem nowej linii na końcu i odejmij jeden.
$((${#$(readlink -f /etc/fstab; echo .)} - 1))
Jeśli to, czego chcesz, to ładunek w danych wyjściowych polecenia, musisz odjąć dwa tutaj, ponieważ wynikiem readlink -f
jest ścieżka kanoniczna plus znak nowej linii.
$((${#$(readlink -f /etc/fstab; echo .)} - 2))
Różni się to od ${#$(readlink -f /etc/fstab)}
rzadkiego, ale możliwego przypadku, gdy sama ścieżka kanoniczna kończy się nową linią.
W tym konkretnym przykładzie w ogóle nie potrzebujesz zewnętrznego narzędzia, ponieważ zsh ma wbudowaną konstrukcję równoważną readlink -f
poprzez modyfikator historii A
.
echo /etc/fstab(:A)
Aby uzyskać długość, użyj modyfikatora historii w rozszerzeniu parametru:
${#${:-/etc/fstab}:A}
Jeśli masz nazwę pliku w zmiennej filename
, byłoby to ${#filename:A}
.
Pociski w stylu Bourne / POSIX
Żadna z czystych powłok Bourne / POSIX (Bourne, ash, mksh, ksh93, bash, yash…) nie ma podobnego rozszerzenia, jakie znam. Jeśli chcesz zastosować podstawienie parametru do wyniku podstawienia polecenia lub zagnieżdżić podstawienia parametrów, użyj kolejnych etapów.
Jeśli chcesz, możesz przekształcić przetwarzanie w funkcję.
command_output_length_sans_trailing_newlines () {
set -- "$("$@")"
echo "${#1}"
}
lub
command_output_length () {
set -- "$("$@"; echo .)"
echo "$((${#1} - 1))"
}
ale zwykle nie ma korzyści; z wyjątkiem ksh93, który powoduje, że dodatkowy widelec może korzystać z danych wyjściowych funkcji, co powoduje spowolnienie skryptu i rzadko ma jakiekolwiek korzyści z czytelności.
Po raz kolejny wyjściem readlink -f
jest ścieżka kanoniczna plus nowy wiersz; jeśli chcesz długość ścieżki kanonicznej, odejmij 2 zamiast 1 cala command_output_length
. Użycie command_output_length_sans_trailing_newlines
daje właściwy wynik tylko wtedy, gdy sama ścieżka kanoniczna nie kończy się na nowej linii.
Bajty kontra postacie
${#…}
ma mieć długość w znakach, a nie w bajtach, co robi różnicę w ustawieniach wielobajtowych. Racjonalnie aktualne wersje ksh93, bash i zsh obliczają długość w znakach zgodnie z wartością LC_CTYPE
w momencie ${#…}
rozwijania konstrukcji. Wiele innych popularnych powłok nie obsługuje tak naprawdę wielobajtowych ustawień narodowych: od myślnika 0.5.7, mksh 46 i posh 0.12.3 ${#…}
zwraca długość w bajtach. Jeśli chcesz, aby długość w znakach była niezawodna, użyj wc
narzędzia:
$(readlink -f /etc/fstab | wc -m)
Tak długo, jak $LC_CTYPE
określa prawidłową lokalizację, możesz być pewien, że spowoduje to błąd (na starej lub ograniczonej platformie, która nie obsługuje ustawień wielobajtowych) lub zwróci prawidłową długość znaków. (W przypadku Unicode „długość w znakach” oznacza liczbę punktów kodowych - liczba glifów to kolejna historia, z powodu komplikacji, takich jak łączenie znaków.)
Jeśli chcesz długość w bajtach, ustaw LC_CTYPE=C
tymczasowo lub użyj wc -c
zamiast wc -m
.
Zliczanie bajtów lub znaków za pomocą wc
obejmuje końcowe znaki nowego wiersza polecenia. Jeśli chcesz długość kanonicznej ścieżki w bajtach, to
$(($(readlink -f /etc/fstab | wc -c) - 1))
Aby uzyskać go w postaci, odejmij 2.
readlink -f /etc/fstab
to 11 znaków. Nie zapomnij nowej linii. W przeciwnym razie zobaczysz,/etc/fstabluser@cern:~$
gdy uruchomisz go z powłoki.