コマンドの出力の文字数を計算するスクリプトを書いています。一歩。
たとえば、このコマンドを使用すると、そのコマンドの出力は 10 文字の長さであるため、readlink -f /etc/fstab
が返されるはずです。10
これは、次のコードを使用して保存された変数ですでに可能です。
variable="somestring";
echo ${#variable};
# 10
残念ながら、コマンドで生成された文字列で同じ数式を使用しても機能しません。
${#(readlink -f /etc/fstab)};
# bash: ${#(readlink -f /etc/fstab)}: bad substitution
まず出力を変数に保存することでこれが可能だと理解しています。
variable=$(readlink -f /etc/fstab);
echo ${#variable};
しかし、余分な手順を削除したいと思います。
これは可能ですか? 組み込みまたは標準のユーティリティのみを使用して、Almquist シェル (sh) との互換性が望ましいです。
答え1
とGNU 式:
$ expr length + "$(readlink -f /etc/fstab)"
10
GNU には、次の引数が、、...のような演算子であっても文字列として扱われるようにする特別な機能+
があります。expr
expr
match
length
+
上記は出力の末尾の改行を削除します。これを回避するには、次のようにします。
$ expr length + "$(readlink -f /etc/fstab; printf .)" - 2
10
結果は減算され2最後の改行readlink
と追加した文字のためです.
。
Unicode文字列では、expr
文字数ではなくバイト数で文字列の長さを返すため、動作しないようです(654行目)
$ LC_ALL=C.UTF-8 expr length ăaa
4
したがって、次のものを使用できます。
$ printf "ăaa" | LC_ALL=C.UTF-8 wc -m
3
POSIX: 正しい:
$ expr " $(readlink -f /etc/fstab; printf .)" : ".*" - 3
10
コマンド置換の前のスペースは、コマンドが で始まる文字列でクラッシュするのを防ぐ-
ため、3 を減算する必要があります。
答え2
シェルの組み込み関数でこれをどうやって行うのかよく分からない(グヌークは) ですが、標準ツールが役立ちます:
文字数を数える whichを使うことができます
wc -m
。残念ながら、最後の改行も数えてしまうので、まずそれを削除する必要があります。readlink -f /etc/fstab | tr -d '\n' | wc -m
もちろん、
awk
readlink -f /etc/fstab | awk '{print length($0)}'
またはPerl
readlink -f /etc/fstab | perl -lne 'print length'
答え3
私は通常次のようにします:
$ echo -n "$variable" | wc -m
10
コマンドを実行するには、次のように変更します。
$ echo -n "$(readlink -f /etc/fstab)" | wc -m
10
このアプローチは、2 つのステップで実行していたものと似ていますが、それらを 1 つの 1 行に組み合わせている点が異なります。
答え4
これは動作しますdash
が、対象の変数が確実に空であるか未設定である必要があります。これが実際には二コマンド -$l
最初に明示的に空にします:
l=;printf '%.slen is %d and result is %s\n' \
"${l:=$(readlink -f /etc/fstab)}" "${#l}" "$l"
出力
len is 10 and result is /etc/fstab
これらはすべてシェルの組み込み関数です (もちろん は含まれませんreadlink
)。ただし、現在のシェルでそのように評価すると、len を取得する前に割り当てを行う必要があることが示唆されます。そのため、フォーマット文字列%.s
の最初の引数を無効にして、の引数リストprintf
の末尾のリテラル値に再度追加します。printf
とeval
:
l=$(readlink -f /etc/fstab) eval 'l=${#l}:$l'
printf %s\\n "$l"
出力
10:/etc/fstab
同じことに近い結果を得ることができますが、最初のコマンドの変数の出力ではなく、stdout に出力されます。
PS4='${#0}:$0' dash -cx '2>&1' "$(readlink -f /etc/fstab)"
...と書かれています...
10:/etc/fstab
...現在のシェル内のどの変数にも値を割り当てずに、ファイル記述子 1 に追加します。