Вопрос или проблема
У меня проблема со скриптом BASH, которую я сузил, но не могу понять, что вижу. Я хочу получить подстроку массива лаконичным способом. Вот что я вижу в bash, с ‘set -x’, чтобы команды печатались по мере выполнения:
$: read -a colours
+ read -a colours
синий зеленый красный желтый розовый фиолетовый
$: echo ${colours[@]}
+ echo синий зеленый красный желтый розовый фиолетовый
синий зеленый красный желтый розовый фиолетовый
$: expr substr "${colours[@]}" 16 6
+ expr substr синий зеленый красный желтый розовый фиолетовый 16 6
expr: ошибка синтаксиса: неожиданный аргумент ‘желтый’
$: expr substr \"${colours[@]}\" 16 6
+ expr substr '"синий' зеленый красный желтый розовый 'фиолетовый"' 16 6
expr: ошибка синтаксиса: неожиданный аргумент ‘желтый’
Последняя попытка команды expr substr
вернула странные кавычки для элементов массива, откуда это взялось? Помогите мне понять, что делает expr substr
здесь, или это ошибка?
ИЗМЕНЕНИЕ: Я перечислил ниже некоторые желаемые поведения на плоской строке в кавычках, но почему я не могу привести массив в кавычках таким же образом?
$: all_colours=${colours[@]}
+ all_colours="синий зеленый красный желтый розовый фиолетовый"
$: expr substr $all_colours 16 6
+ expr substr синий зеленый красный желтый розовый фиолетовый 16 6
expr: ошибка синтаксиса: неожиданный аргумент ‘желтый’
$: expr substr "$all_colours" 16 6
+ expr substr 'синий зеленый красный желтый розовый фиолетовый' 16 6
желтый
Expr – это инструмент командной строки, он независим от bash. Он не знает ничего о массивах. Он получает аргументы командной строки, именно те, которые мы обозначаем как $1
, $2
, $3
и т.д. в наших скриптах.
Важно помнить: bash знает массивы, но когда вы вызываете двоичный файл, он может получать только список аргументов в качестве своих параметров.
Если вы вызываете expr
с массивом, развёрнутым по вашему синтаксису, вы получите то, что указали. expr substr
ожидает числа, вы даете ему много текстовых слов, поэтому он будет жаловаться на слишком много аргументов и неправильный тип.
Я не уверен, что вы пытаетесь сделать с этой подстрокой – массив может иметь диапазон, или “подмассив”, или интервал, но я не уверен, как вы определяете подстроку массива.
Ответ или решение
Для решения вашей задачи, связанной с обработкой массивов в Bash и использованием команды expr
, необходимо обратить внимание на несколько ключевых аспектов, касающихся взаимодействия между массивами Bash и внешними командами.
Понимание работы expr
с массивами
Команда expr
является утилитой, которая предназначена для выполнения различных операций на числах и строках, однако при этом она не имеет представления о массивах в Bash. Это следует учитывать при работе с аргументами, которые передаются в expr
.
Когда вы передаете массив в команду expr
, происходит следующее:
-
Расширение массива: При использовании конструкции
${colours[@]}
Bash расширяет массив до списка отдельных аргументов. В вашем случае, когда вы вызываетеexpr substr "${colours[@]}" 16 6
, каждый элемент массива передается как отдельный аргумент. -
Ошибки при передаче аргументов: Формат вызова
expr substr
требует, чтобы в качестве первого аргумента была строка (в которой будет выполняться поиск подстроки), а следующие два аргумента — это начальная позиция и длина подстроки. Ваша команда вызывает ошибку "unexpected argument" из-за неправильного количества аргументов, так какexpr
ожидает строку, а получает список.
Разбор примеров
В вашем примере:
expr substr "${colours[@]}" 16 6
Bash пытается передать несколько аргументов вместо одной строки, что вызывает ошибку. Каждый элемент массива передается как отдельный аргумент. В результате, expr
интерпретирует это как многократные входные данные, в том числе и слово "yellow".
Когда вы используете:
all_colours=${colours[@]}
вы корректно объединяете массив в одну строку, и в этом случае:
expr substr "$all_colours" 16 6
работает, поскольку строка, полученная из массива, передается как единый аргумент, что делает вызов корректным с точки зрения синтаксиса.
Рекомендации
Если вы хотите работать с элементами массива и получать подстроки, то вам, возможно, стоит использовать другие подходы, такие как:
- Циклы по элементам массива: Извлечение нужных элементов по индексам.
- Использование встроенных функций Bash: Например, с помощью подстановки и манипуляций со строками.
Пример извлечения элемента массива:
# Получить подстроку из определенного элемента массива
start_index=0
length=6
echo "${colours[0]:$start_index:$length}"
Заключение
Ваша проблема связана не с ошибкой в expr
, а с тем, как Bash обрабатывает массивы и передает их в внешние команды. Для успешного получения подстрок необходимо объединить массив в строку или работать с отдельными элементами напрямую. Таким образом, понимание ограничений между Bash и командами, основанными на аргументах, позволит более эффективно обрабатывать данные в вашем сценарии.