外部ユーティリティを呼び出すこともできますが(他の回答を参照)、スクリプトが遅くなり、適切な配管を行うことが困難になります。
Zsh
zshでは${#$(readlink -f /etc/fstab)}
、コマンド置換の長さを取得するように書き込むことができます。これはコマンド出力の長さではなく、末尾の改行なしの出力の長さであることに注意してください。
出力の正確な長さが必要な場合は、最後に余分な非改行文字を出力し、1つ減算します。
$((${#$(readlink -f /etc/fstab; echo .)} - 1))
コマンドの出力のペイロードが必要な場合は、ここで2を減算する必要がありreadlink -f
ます。これは、の出力が正規パスと改行であるためです。
$((${#$(readlink -f /etc/fstab; echo .)} - 2))
これは${#$(readlink -f /etc/fstab)}
、正規のパス自体が改行で終わるというまれなケースとは異なります。
この特定の例では、外部ユーティリティはまったく必要ありません。zshにはreadlink -f
、履歴修飾子を介したと同等の組み込みの構成要素があるためA
です。
echo /etc/fstab(:A)
長さを取得するには、パラメーター展開で履歴修飾子を使用します。
${#${:-/etc/fstab}:A}
変数にファイル名がある場合filename
、それはそうなります${#filename:A}
。
Bourne / POSIXスタイルのシェル
純粋なBourne / POSIXシェル(Bourne、ash、mksh、ksh93、bash、yash…)には、私が知っている同様の拡張機能はありません。コマンド置換の出力またはパラメーター置換のネストにパラメーター置換を適用する必要がある場合は、連続するステージを使用します。
必要に応じて、処理を関数に組み込むことができます。
command_output_length_sans_trailing_newlines () {
set -- "$("$@")"
echo "${#1}"
}
または
command_output_length () {
set -- "$("$@"; echo .)"
echo "$((${#1} - 1))"
}
しかし、通常はメリットはありません。ksh93を除き、追加のフォークが関数の出力を使用できるようにするため、スクリプトが遅くなり、読みやすさの利点はほとんどありません。
ここでも、の出力readlink -f
は正規パスと改行です。正規パスの長さが必要な場合は、で1ではなく2を引きcommand_output_length
ます。使用するには、command_output_length_sans_trailing_newlines
正規のパス自体が改行で終わっていない場合にのみ、正しい結果を与えます。
バイトと文字
${#…}
バイト単位ではなく、文字単位の長さが想定されているため、マルチバイトロケールでは違いがあります。ksh93、bash、およびzshの合理的に最新のバージョンはLC_CTYPE
、${#…}
構成が展開されたときのの値に従って文字数で長さを計算します。他の多くの一般的なシェルは、実際にはマルチバイトロケールをサポートしていません。ダッシュ0.5.7以降、mksh 46およびposh 0.12.3では${#…}
、長さをバイト単位で返します。信頼できる方法で文字の長さを知りたい場合は、wc
ユーティリティを使用してください:
$(readlink -f /etc/fstab | wc -m)
$LC_CTYPE
有効なロケールを指定している限り、これがエラーになるか(マルチバイトロケールをサポートしていない古いプラットフォームまたは制限されたプラットフォームで)、正しい長さの文字を返すと確信できます。(Unicodeの場合、「文字の長さ」はコードポイントの数を意味します。文字の結合などの複雑さのため、グリフの数はさらに別の話です。)
長さをバイト単位で取得したい場合は、LC_CTYPE=C
一時的に設定するか、のwc -c
代わりに使用してくださいwc -m
。
でバイトまたは文字をカウントwc
すると、コマンドの後続の改行が含まれます。正規パスの長さをバイト単位で知りたい場合は、
$(($(readlink -f /etc/fstab | wc -c) - 1))
文字で取得するには、2を引きます。
readlink -f /etc/fstab
は11文字です。改行を忘れないでください。それ以外の場合は/etc/fstabluser@cern:~$
、シェルから実行したときに表示されます。