Что делает expr при обработке массивов?

Вопрос или проблема

У меня проблема со скриптом 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, происходит следующее:

  1. Расширение массива: При использовании конструкции ${colours[@]} Bash расширяет массив до списка отдельных аргументов. В вашем случае, когда вы вызываете expr substr "${colours[@]}" 16 6, каждый элемент массива передается как отдельный аргумент.

  2. Ошибки при передаче аргументов: Формат вызова expr substr требует, чтобы в качестве первого аргумента была строка (в которой будет выполняться поиск подстроки), а следующие два аргумента — это начальная позиция и длина подстроки. Ваша команда вызывает ошибку "unexpected argument" из-за неправильного количества аргументов, так как expr ожидает строку, а получает список.

Разбор примеров

В вашем примере:

expr substr "${colours[@]}" 16 6

Bash пытается передать несколько аргументов вместо одной строки, что вызывает ошибку. Каждый элемент массива передается как отдельный аргумент. В результате, expr интерпретирует это как многократные входные данные, в том числе и слово "yellow".

Когда вы используете:

all_colours=${colours[@]}

вы корректно объединяете массив в одну строку, и в этом случае:

expr substr "$all_colours" 16 6

работает, поскольку строка, полученная из массива, передается как единый аргумент, что делает вызов корректным с точки зрения синтаксиса.

Рекомендации

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

  1. Циклы по элементам массива: Извлечение нужных элементов по индексам.
  2. Использование встроенных функций Bash: Например, с помощью подстановки и манипуляций со строками.

Пример извлечения элемента массива:

# Получить подстроку из определенного элемента массива
start_index=0
length=6
echo "${colours[0]:$start_index:$length}"

Заключение

Ваша проблема связана не с ошибкой в expr, а с тем, как Bash обрабатывает массивы и передает их в внешние команды. Для успешного получения подстрок необходимо объединить массив в строку или работать с отдельными элементами напрямую. Таким образом, понимание ограничений между Bash и командами, основанными на аргументах, позволит более эффективно обрабатывать данные в вашем сценарии.

Оцените материал
Добавить комментарий

Капча загружается...