Anda dapat memanggil utilitas eksternal (lihat jawaban lain), tetapi mereka akan membuat skrip Anda lebih lambat, dan sulit untuk memperbaiki saluran air.
Zsh
Di zsh, Anda bisa menulis ${#$(readlink -f /etc/fstab)}
untuk mendapatkan panjang substitusi perintah. Perhatikan bahwa ini bukan panjang dari output perintah, itu adalah panjang dari output tanpa baris baru.
Jika Anda ingin panjang pasti dari output, output karakter non-newline tambahan di akhir, dan kurangi satu.
$((${#$(readlink -f /etc/fstab; echo .)} - 1))
Jika yang Anda inginkan adalah payload di output perintah, maka Anda perlu mengurangi dua di sini, karena outputnya readlink -f
adalah jalur kanonik ditambah baris baru.
$((${#$(readlink -f /etc/fstab; echo .)} - 2))
Ini berbeda dari ${#$(readlink -f /etc/fstab)}
kasus yang jarang tetapi mungkin terjadi di mana jalur kanonik itu sendiri berakhir di baris baru.
Untuk contoh khusus ini, Anda tidak memerlukan utilitas eksternal sama sekali, karena zsh memiliki konstruksi bawaan yang setara dengan readlink -f
, melalui pengubah riwayat A
.
echo /etc/fstab(:A)
Untuk mendapatkan panjangnya, gunakan pengubah riwayat dalam ekspansi parameter:
${#${:-/etc/fstab}:A}
Jika Anda memiliki nama file dalam variabel filename
, itu akan menjadi ${#filename:A}
.
Kerang Bourne / gaya POSIX
Tak satu pun dari shell Bourne / POSIX murni (Bourne, ash, mksh, ksh93, bash, yash ...) memiliki ekstensi serupa yang saya ketahui. Jika Anda perlu menerapkan substitusi parameter ke output substitusi perintah atau ke substitusi parameter sarang, gunakan tahapan berturut-turut.
Anda dapat memasukkan pemrosesan ke dalam fungsi jika diinginkan.
command_output_length_sans_trailing_newlines () {
set -- "$("$@")"
echo "${#1}"
}
atau
command_output_length () {
set -- "$("$@"; echo .)"
echo "$((${#1} - 1))"
}
tetapi biasanya tidak ada manfaatnya; kecuali dengan ksh93, yang menyebabkan garpu tambahan untuk dapat menggunakan output dari fungsi, sehingga membuat skrip Anda lebih lambat, dan jarang ada manfaat keterbacaan.
Sekali lagi, output dari readlink -f
adalah jalur kanonik ditambah baris baru; jika Anda ingin panjang jalur kanonik, kurangi 2 bukannya 1 in command_output_length
. Menggunakan command_output_length_sans_trailing_newlines
memberikan hasil yang benar hanya ketika jalur kanonik itu sendiri tidak berakhir di baris baru.
Bytes vs karakter
${#…}
seharusnya menjadi panjang dalam karakter, bukan dalam byte, yang membuat perbedaan dalam lokal multibyte. Versi terbaru dari ksh93, bash, dan zsh menghitung panjang karakter sesuai dengan nilai LC_CTYPE
pada saat ${#…}
konstruk diperluas. Banyak shell umum lainnya tidak benar-benar mendukung local multibyte: pada dash 0.5.7, mksh 46 dan posh 0.12.3, ${#…}
mengembalikan panjang dalam byte. Jika Anda ingin panjang karakter dengan cara yang dapat diandalkan, gunakan wc
utilitas:
$(readlink -f /etc/fstab | wc -m)
Selama $LC_CTYPE
menetapkan lokal yang valid, Anda dapat yakin bahwa ini akan salah (pada platform kuno atau terbatas yang tidak mendukung lokal multibyte) atau mengembalikan panjang karakter yang benar. (Untuk Unicode, "panjang karakter" berarti jumlah titik kode - jumlah mesin terbang adalah cerita lain, karena komplikasi seperti menggabungkan karakter.)
Jika Anda ingin panjang dalam byte, atur LC_CTYPE=C
sementara, atau gunakan wc -c
sebagai ganti wc -m
.
Menghitung byte atau karakter dengan wc
menyertakan baris baru yang tertinggal dari perintah. Jika Anda ingin panjang jalur kanonik dalam byte, itu
$(($(readlink -f /etc/fstab | wc -c) - 1))
Untuk mendapatkannya dalam karakter, kurangi 2.
readlink -f /etc/fstab
adalah 11 karakter. Jangan lupa baris baru. Kalau tidak, Anda akan melihat/etc/fstabluser@cern:~$
ketika Anda menjalankannya dari shell.