Я пытаюсь использовать массивы в оболочке Bourne ( /bin/sh
). Я обнаружил, что способ инициализации элементов массива:
arr=(1 2 3)
Но он сталкивается с ошибкой:
syntax error at line 8: `arr=' unexpected
Теперь в посте, где я нашел этот синтаксис, говорится, что он предназначен bash
, но я не смог найти какой-либо отдельный синтаксис для оболочки Bourne. Синтаксис также одинаковый /bin/sh
?
shell
array
bourne-shell
SubhasisM
источник
источник
Ответы:
/bin/sh
В настоящее время вряд ли когда-либо будет оболочкой Bourne в каких-либо системах (даже Solaris, которая была одной из последних крупных систем, включившей ее, теперь переключилась на POSIX sh для своего / bin / sh в Solaris 11)./bin/sh
была оболочкой Томпсона в начале 70-х годов. Оболочка Bourne заменила ее в Unix V7 в 1979 году./bin/sh
в течение многих лет после этого была оболочкой Борна (или оболочкой Альмквиста, бесплатной повторной реализацией на BSD).В настоящее время
/bin/sh
чаще используется тот или иной интерпретатор дляsh
языка POSIX, который сам основан на подмножестве языка ksh88 (и расширенном наборе языка оболочки Bourne с некоторыми несовместимостями).Оболочка Bourne или спецификация языка POSIX sh не поддерживают массивы. Или , скорее , они имеют только один массив: позиционные параметры (
$1
,$2
,$@
, так что один массив на функцию, а).У ksh88 были массивы, которые вы установили
set -A
, но они не были указаны в POSIX sh, поскольку синтаксис неудобен и не очень удобен.Другие оболочки с массивами / списками переменных включают в себя:
csh
/tcsh
,rc
,es
,bash
(которые в основном скопированы с синтаксисом КШ в ksh93 пути),yash
,zsh
,fish
каждый с другим синтаксисом (rc
оболочкой один раз-быть преемник Unix,fish
иzsh
являются наиболее последовательными из них) ...В стандартной комплектации
sh
(также работает в современных версиях оболочки Bourne):(обратите внимание, что в оболочке Bourne и ksh88,
$IFS
должен содержать символ пробела для"$@"
правильной работы (ошибка), а в оболочке Bourne вы не можете получить доступ к элементам выше$9
(${10}
не будет работать, вы все равно можете сделатьshift 1; echo "$9"
или перебрать их)).источник
"${@:2:4}"
. Конечно, я вижу сходство , но я не рассматриваю позиционные параметры как массив как таковой."$@"
действует как массив (например , массивыcsh
,rc
,zsh
,fish
,yash
...), это больше на Korn / Баш «массивы», которые на самом деле не массивы, но некоторые форма ассоциативных массивов с ключами, ограниченными положительными целыми числами (у них также есть индексы, начинающиеся с 0 вместо 1, как во всех других оболочках с массивами и "$ @"). Оболочки, которые поддерживают нарезку, могут нарезать $ @ точно так же (ksh93 / bash неловко добавляет $ 0 к позиционным параметрам, когда вы нарезаете «$ @»).В простой оболочке Борна нет массивов. Вы можете использовать следующий способ для создания массива и его обхода:
Независимо от того, какой способ использования массивов
sh
вы бы выбрали, он всегда будет громоздким. Подумайте об использовании другого языка, например,Python
или,Perl
если вы можете, если вы не застряли на очень ограниченной платформе или хотите чему-то научиться.источник
$(...)
синтаксиса. Таким образом, у вас действительно должна быть оболочка Борна. Вы на Солярисе 10 или раньше? Скорее всего, у вас тоже не будетseq
. В Solaris 10 и более ранних версиях у / usr / xpg4 / bin / sh должен быть стандартsh
вместо оболочки Bourne. Использованиеseq
этого способа тоже не очень хорошо.seq
этого способа не хорошо?$(...)
более`
, но OP - х/bin/sh
, вероятно, Bourne оболочки, а не оболочка POSIX. Помимо того,seq
что это не стандартная команда, выполнение$(seq 100)
означает сохранение всего вывода в памяти, а это означает, что оно зависит от текущего значения $ IFS, содержащего символ новой строки и не содержащего цифр. Лучше всего использоватьi=1; while [ "$i" -le 100 ]; ...; i=$(($i + 1)); done
(хотя это не сработает и в оболочке Bourne)./bin/sh
синтаксис, склоняюсь к тому, что люди думают, что можно использовать неправильный#!/bin/sh
shebang, а затем ломает свои сценарии, когда другие люди пытаются их использовать. Вам бы не советовали не публиковать такую приманку. :)Как говорили другие, Bourne Shell не имеет истинных массивов.
Однако, в зависимости от того, что вам нужно сделать, должно быть достаточно разделенных строк:
Если типичные разделители (пробел, табуляция и перевод строки) недостаточны, вы можете установить
IFS
любой разделитель, какой захотите, перед циклом.И если вам нужно построить массив программно, вы можете просто создать строку с разделителями.
источник
split+glob
оператор).Способ имитации массивов в тире (его можно адаптировать к любому количеству измерений массива): (Обратите внимание, что для использования
seq
команды требуетсяIFS
значение '' (ПРОБЕЛ = значение по умолчанию). Вы можете использоватьwhile ... do ...
илиdo ... while ...
циклы вместо этого, чтобы избежать этого (я держуseq
в поле зрения лучшей иллюстрации того, что делает код).)источник
local
поддерживается обоимиbash
иdash
, это не POSIX.seq
это также не команда POSIX. Вы, вероятно, должны упомянуть, что ваш код делает некоторые предположения о текущем значении $ IFS (если вы избегаете использованияseq
и цитируете свои переменные, этого можно избежать)