bash配列インデックス番号の文字列の長さを見つける方法は?

bash配列インデックス番号の文字列の長さを見つける方法は?

Bashでは、関数が長さを知らない単純な配列を生成すると仮定します。配列が変換され、画面に印刷されます。各行の横には、選択できる小さなインデックス番号があります。スペースは限られており、プレゼンテーションは完璧でなければなりませんでした。

どうやって見つけることができますか?文字列の長さ~のインデックス番号自体(フォーマット目的で)これは配列の値ではありません。たとえば、配列に334,345項目がある場合(最後の項目印刷を使用echo ${hugearray[334344]})、それは6私が探しているものです。

ncursesターゲットシステムにtputやその他の「クールな」フォーマットユーティリティがないため、bashに滞在する必要があります。自分自身だけを攻撃します。

${#WORD[@]}アイテムの総数を知らせ、これを達成するためにいくつかの基本構成を構築します。

$〉pkglist+=($(brew list -1)) # ← I'm testing on a Mac.
$〉printf "%s\n" ${pkglist[@]}
automake
xquartz

$〉echo ${#pkglist[@]}
68

$〉indexlength=${#pkglist[@]}
$〉echo ${#indexlength}
2

動作しますが、完全にエレガントではありません。弁護すると、私は開発者ではありません。しかし、私はこれを行うより良いより簡単な方法、入れ子になった間接参照、または他のbash桟橋がすでに存在していることを願っています。しかし、一般的なもの実際のデータにどのような影響を与えるかは十分に混乱しているので、後悔する前に尋ねるのが最善だと思います(ターゲットシステムにはrootアカウントしかありません)。あなたはいますか?

ありがとうございます!

答え1

Macosを使用している場合はzshにアクセスできる必要があるため、bashを使用する必要はありません。

zshでは、配列の長さは$#arraycshに等しく、パラメータ拡散演算子を入れ子にすることができるので、${#${#array}}1を実行して配列長の小数表現長を得ることができます。

$ a=(qwe asdasd qewqw)
$ () {printf "%${#${#a}}d %s\n" "${@:^a}"} {1..$#a}
1 qwe
2 asdasd
3 qweqe
$ a=( {a..m} )
$ () {printf "%${#${#a}}d %s\n" "${@:^a}}" {1..$#a}
 1 a
 2 b
 3 c
 4 d
 5 e
 6 f
 7 g
 8 h
 9 i
10 j
11 k
12 l
13 m

すべてのarray=(...)array+=(...){x..y}bashによってzshからコピーされました(通常kshを介して間接的に)。{1..$expansion}zshまたはkshでは機能しますが、bashでは機能しません。

配列${a:^b}圧縮演算子と() {code} args匿名関数はまだzshにのみ適用されます。


bashを使用する必要がある場合は、あなたのように2つのステップで行うのがおそらく最善でしょう。

$(((l=${#array[@]}),SHLVL[l=\${#l}],l))配列インデックスの遅延評価に依存して、1つの拡張でこれを行うことができますが、これは読みやすさに役立たず、将来も保証されない可能性があります。

また、bashでは(kshのようにbashの配列デザインは残念ながらコピーされています)、配列は実際には配列ではなく連想配列に近いです。キーは正の整数で、0から始まります(他のほとんどの殻とは異なり、1)

bash-5.1$ a=( [5]=123 [123]=qwe [4567]=asd )
bash-5.1$ typeset -p a
declare -a a=([5]="123" [123]="qwe" [4567]="asd")
bash-5.1$ echo "${#a[@]}"
3

3配列の要素数ですが、必要な最も高いキー値ではありません。

bash-5.1$ keys=("${!a[@]}")
bash-5.1$ echo "${keys[@]: -1}"
4567

したがって、ソートされたキーと値を印刷するには、次のものが必要です。

printarray() {
  local -n arr="$1"
  local -a keys=("${!arr[@]}")
  local highest_key="${keys[@]: -1}"
  local key_width="${#highest_key}"
  local key
  for key in "${keys[@]}"; do
    printf '%*d %s\n' "$key_width" "$key" "${arr[key]}"
  done
}
bash-5.1$ printarray a
   5 123
 123 qwe
4567 asd

(Macosの古代bashでは動作しません。bash local -n4.3以降が必要です)


¹は、${#$#array}Kornスタイルの演算子を使用して最初から削除した後に長さとして扱われるため、機能しません${#${$#array}}$$array${var#pattern}

答え2

あなたが言ったように、これは一種のBASH魔法かもしれませんか? - 追加の変数はありませんが、
: $((${#pkglist[*]}-1)); echo ${#_}; $_はデバッグの問題を引き起こす可能性があります。 - 長いスクリプト

答え3

編集する:@ilkkachuが親切に知っているように、変数の長さを見つける最も簡単な方法は、${#variable}外部ツールを使用するよりもを使用することです。この回答は無視してください。すぐに削除します。私は本当に恥ずかしいです!

数字の桁数を確認するには、数字に 1 を加えたログに 1 を足し、小数部を引くだけです。ただし、バイナリ電卓にはbcこれを行う便利な機能があります。

echo "length(334344)" | bc

必要に応じて6を印刷します。引数がlength整数でない場合は、小数点カンマなしで実際の桁数を計算します(つまり、length(3.4560)5になります)。

echo二重引用符の中に Bash 変数拡張を使用して Bash 変数を挿入するには:

x=334344
echo "length($x)" | bc

簡単に呼び出すためにこれを関数として書くことができます。

function num_digits {
#determine hoy many digits has a number
#param number
    local number="$1"
    echo "length($number)" | bc
}

次に、次のように使用します。

lendigits=$(num_digits 334344)

または変数を使用してください。

x=334344
lendigits=$(num_digits $x)

メモ:Linuxディストリビューションにまだインストールされていない場合は、ディストリビューションbcのパッケージマネージャを使用して追加できます。

ノート2:もちろん、関数の代わりに式を直接使用することもできます。

x=334344
lendigits=$(echo "length($x)" | bc)

ただし、読みやすさが低いため、後で他のスクリプトで使用するためにコピーできる特別なタスクが識別され、関数にカプセル化される少し長いスクリプトが好まれます。

関連情報