Как получить длину массива BASH с помощью описательного / читабельного оператора? - PullRequest
0 голосов
/ 07 мая 2019

Кажется, что стандартный способ получить длину массива в BASH - это ${#myArray[@]}, например:

myArray=( 1 3 5 7 9 )
length=${#myArray[@]}

echo "length: $length" # length: 5

Этот синтаксис отвратительно загадочный и нечитаемый, хотя.Есть ли какой-нибудь встроенный метод, похожий на count( $myArray ), myArray.length и т. Д.?

Ответы [ 2 ]

2 голосов
/ 07 мая 2019

Вы можете легко реализовать count "${myArray[@]}", если это заставит вас чувствовать себя лучше:

count() { echo "$#"; }
length=$(count "${myArray[@]}")

... или как альтернатива, которая не требует подстановки команд(и удар по производительности сопровождающего), чтобы присвоить результат:

assignCount() {
  local -n assignCount_arr=$2
  printf -v "$1" %s "${#assignCount_arr[@]}"
}
assignCount length myArray

Однако это не совсем упрощает синтаксис и делает его чистым - если его неправильно использовать, пропуская кавычки, f / e,массивы с содержимым, которое может быть интерпретировано как глобальные выражения или содержимое которого содержит символы в IFS, могут возвращать неверные значения.

Честно говоря, bash не является простым в использовании языком и пытается рассматривать его так, как если бы онгде приводит к многочисленным, серьезным ошибкам .Гораздо разумнее, чтобы «здесь были драконы» были видны заранее, чем позволить людям самоуспокоиться и оставить серьезные ошибки на месте благодаря , а не изучению входов и выходов модели исполнения и синтаксиса.

0 голосов
/ 07 мая 2019

Я выбросил этот ответ как жаворонок.Имейте в виду, что eval - это дыра в безопасности, через которую вы можете вести бомбу грузовика, если данные не подвергаются тщательному мониторингу и / или очистке.Eval был чрезмерно легкомысленным использованием сарказма, который я должен был сделать более ясным.(Я думал, что строка о Java или Perl прояснит это, но я не думаю, lol)

Вот более разумная версия, которую вы заметите, использовав решение Чарльза Даффи почти точно.

lengthOf() {
  local -n standin=$1   # standin is a *reference* to the name passed
  echo "${#standin[@]}"
}

Это работает так же, как мой оригинал ниже, но рассмотрим типичное использование - в большинстве случаев вы просто хотите сохранить возврат, поэтому идиома будет

len=$( lengthOf someArray )

Если это так, Пожалуйста, см. Решение Чарльза, поскольку для этого гораздо лучше назначить переменную непосредственно в том же вызове.

Оригинальный ответ

Если вам просто нужен синтаксический сахар, вам придется вникать в сорняки тех частей, которые вам не нравятся, иможет быть, это вызовет некоторые довольно уродливые проблемы с безопасностью ... но вот вариант, для удовольствия от упражнения.Кто-то наверняка предложит уточнения.

lengthOf() { eval "echo \${#$1[@]}"; }

Теперь, если у вас есть массив, объявленный как a=( a b c ), вы можете сделать это:

lengthOf a

, и он напечатает 3.Только не ожидайте, что он даст вам длину строки вместо массива ....

Bash - это все о контексте, поэтому, если вас беспокоит небольшое синтаксическое усилие, может быть, вы должны попробовать другой язык ... как Java, или Perl, лол!;)

...