Puoi chiamare utility esterne (vedi altre risposte), ma rallenteranno il tuo script ed è difficile trovare il giusto impianto idraulico.
zsh
In zsh, puoi scrivere ${#$(readlink -f /etc/fstab)}
per ottenere la lunghezza della sostituzione del comando. Si noti che questa non è la lunghezza dell'output del comando, è la lunghezza dell'output senza alcuna nuova riga finale.
Se si desidera la lunghezza esatta dell'output, emettere un carattere extra non newline alla fine e sottrarre uno.
$((${#$(readlink -f /etc/fstab; echo .)} - 1))
Se quello che vuoi è il payload nell'output del comando, allora devi sottrarre due qui, perché l'output di readlink -f
è il percorso canonico più una nuova riga.
$((${#$(readlink -f /etc/fstab; echo .)} - 2))
Ciò differisce dal ${#$(readlink -f /etc/fstab)}
raro ma possibile caso in cui il percorso canonico stesso termina in una nuova riga.
Per questo esempio specifico, non hai bisogno di alcuna utility esterna, perché zsh ha un costrutto integrato che è equivalente a readlink -f
, tramite il modificatore di cronologia A
.
echo /etc/fstab(:A)
Per ottenere la lunghezza, utilizzare il modificatore della cronologia in un'espansione dei parametri:
${#${:-/etc/fstab}:A}
Se hai il nome del file in una variabile filename
, sarebbe ${#filename:A}
.
Conchiglie tipo Bourne / POSIX
Nessuna delle shell Bourne / POSIX pure (Bourne, ash, mksh, ksh93, bash, yash ...) ha un'estensione simile che io conosca. Se è necessario applicare una sostituzione di parametri all'output di una sostituzione di comando o nidificare sostituzioni di parametri, utilizzare le fasi successive.
Se lo desideri, puoi inserire l'elaborazione in una funzione.
command_output_length_sans_trailing_newlines () {
set -- "$("$@")"
echo "${#1}"
}
o
command_output_length () {
set -- "$("$@"; echo .)"
echo "$((${#1} - 1))"
}
ma di solito non ci sono benefici; eccetto con ksh93, questo fa sì che un fork extra sia in grado di usare l'output della funzione, quindi rallenta lo script e raramente ci sono vantaggi di leggibilità.
Ancora una volta, l'output di readlink -f
è il percorso canonico più una nuova riga; se vuoi la lunghezza del percorso canonico, sottrai 2 invece di 1 pollice command_output_length
. L'utilizzo command_output_length_sans_trailing_newlines
dà il risultato giusto solo quando il percorso canonico stesso non termina in una nuova riga.
Byte vs caratteri
${#…}
dovrebbe essere la lunghezza in caratteri, non in byte, il che fa la differenza nei locali multibyte. Versioni ragionevolmente aggiornate di ksh93, bash e zsh calcolano la lunghezza in caratteri in base al valore LC_CTYPE
al momento dell'espansione del ${#…}
costrutto. Molte altre shell comuni non supportano realmente le localizzazioni multibyte: dal trattino 0.5.7, mksh 46 e posh 0.12.3, ${#…}
restituisce la lunghezza in byte. Se si desidera la lunghezza in caratteri in modo affidabile, utilizzare l' wc
utilità:
$(readlink -f /etc/fstab | wc -m)
Fintanto che $LC_CTYPE
designa una locale valida, puoi essere sicuro che questo si risolverà in un errore (su una piattaforma antica o limitata che non supporta le impostazioni locali multibyte) o restituirà la lunghezza corretta in caratteri. (Per Unicode, "lunghezza in caratteri" indica il numero di punti di codice - il numero di glifi è ancora un'altra storia, a causa di complicazioni come la combinazione di caratteri.)
Se si desidera la lunghezza in byte, impostare LC_CTYPE=C
temporaneamente o utilizzare wc -c
invece di wc -m
.
Il conteggio di byte o caratteri wc
include tutte le nuove righe finali del comando. Se vuoi la lunghezza del percorso canonico in byte, lo è
$(($(readlink -f /etc/fstab | wc -c) - 1))
Per ottenere in caratteri, sottrarre 2.
readlink -f /etc/fstab
è di 11 caratteri. Non dimenticare la nuova riga. Altrimenti vedresti/etc/fstabluser@cern:~$
quando l'hai eseguito da una shell.