Vous pouvez appeler des utilitaires externes (voir les autres réponses), mais ils ralentiront votre script et il est difficile de bien faire la plomberie.
Zsh
Dans zsh, vous pouvez écrire ${#$(readlink -f /etc/fstab)}
pour obtenir la longueur de la substitution de commande. Notez que ce n'est pas la longueur de la sortie de la commande, c'est la longueur de la sortie sans retour à la ligne.
Si vous voulez la longueur exacte de la sortie, sortez un caractère supplémentaire non-retour à la fin et soustrayez-en un.
$((${#$(readlink -f /etc/fstab; echo .)} - 1))
Si ce que vous voulez est la charge utile dans la sortie de la commande, vous devez soustraire deux ici, car la sortie de readlink -f
est le chemin canonique plus une nouvelle ligne.
$((${#$(readlink -f /etc/fstab; echo .)} - 2))
Cela diffère du ${#$(readlink -f /etc/fstab)}
cas rare mais possible où le chemin canonique lui-même se termine par une nouvelle ligne.
Pour cet exemple spécifique, vous n'avez absolument pas besoin d'un utilitaire externe, car zsh a une construction intégrée équivalente à readlink -f
, via le modificateur d'historique A
.
echo /etc/fstab(:A)
Pour obtenir la longueur, utilisez le modificateur d'historique dans une extension de paramètre:
${#${:-/etc/fstab}:A}
Si vous avez le nom de fichier dans une variable filename
, ce serait ${#filename:A}
.
Coquilles de style Bourne / POSIX
Aucun des shells Bourne / POSIX purs (Bourne, ash, mksh, ksh93, bash, yash…) n'a une extension similaire à ma connaissance. Si vous devez appliquer une substitution de paramètres à la sortie d'une substitution de commandes ou imbriquer des substitutions de paramètres, utilisez des étapes successives.
Vous pouvez bourrer le traitement dans une fonction si vous le souhaitez.
command_output_length_sans_trailing_newlines () {
set -- "$("$@")"
echo "${#1}"
}
ou
command_output_length () {
set -- "$("$@"; echo .)"
echo "$((${#1} - 1))"
}
mais il n'y a généralement aucun avantage; sauf avec ksh93, cela permet à un fork supplémentaire de pouvoir utiliser la sortie de la fonction, donc cela rend votre script plus lent, et il y a rarement un avantage de lisibilité.
Encore une fois, la sortie de readlink -f
est le chemin canonique plus une nouvelle ligne; si vous voulez la longueur du chemin canonique, soustrayez 2 au lieu de 1 po command_output_length
. L'utilisation command_output_length_sans_trailing_newlines
donne le bon résultat uniquement lorsque le chemin canonique lui-même ne se termine pas par une nouvelle ligne.
Octets vs caractères
${#…}
est censé être la longueur en caractères, pas en octets, ce qui fait la différence dans les paramètres régionaux multi-octets. Des versions raisonnablement à jour de ksh93, bash et zsh calculent la longueur en caractères selon la valeur de LC_CTYPE
au moment où la ${#…}
construction est développée. De nombreux autres shells courants ne prennent pas vraiment en charge les paramètres régionaux multioctets: à partir du tiret 0.5.7, mksh 46 et posh 0.12.3, ${#…}
renvoie la longueur en octets. Si vous voulez que la longueur en caractères soit fiable, utilisez l' wc
utilitaire:
$(readlink -f /etc/fstab | wc -m)
Tant que $LC_CTYPE
désigne un paramètre régional valide, vous pouvez être sûr que cela entraînera une erreur (sur une plate-forme ancienne ou restreinte qui ne prend pas en charge les paramètres régionaux à plusieurs octets) ou renverra la longueur correcte en caractères. (Pour Unicode, «longueur en caractères» signifie le nombre de points de code - le nombre de glyphes est encore une autre histoire, en raison de complications telles que la combinaison de caractères.)
Si vous voulez la longueur en octets, définissez LC_CTYPE=C
temporairement ou utilisez à la wc -c
place de wc -m
.
Le comptage d'octets ou de caractères avec wc
inclut tous les retours à la ligne de fin de la commande. Si vous voulez la longueur du chemin canonique en octets, c'est
$(($(readlink -f /etc/fstab | wc -c) - 1))
Pour l'obtenir en caractères, soustrayez 2.
readlink -f /etc/fstab
est de 11 caractères. N'oubliez pas la nouvelle ligne. Sinon, vous verriez/etc/fstabluser@cern:~$
quand vous l'avez exécuté à partir d'un shell.