LINUX.ORG.RU

bash, массивы и кавычки

 


0

1

В bash кавычки в некоторых случаях нужны но в некоторых наоборот. В следующем примере мне казалось что если написать «${LIST[@]}» то в цикле будет один элемент.

LIST=({1..10})

for i in "${LIST[@]}" ; do
    echo "${i}"
done

Но этот пример выводит все элементы массива. Почему здесь кавычки не «склеивают» элементы массива?

★★★★★

Ответ на: комментарий от vodz

А, понятно, это потому я что я перешёл со звёздочки на собаку. Пишут что так работает лучше, но в чём разница я пока не понял.

a=({1..10})
for i in ${a[@]}; do echo "$i"; done
for i in "${a[@]}"; do echo "$i"; done
for i in "${a[*]}"; do echo "$i"; done

Со звёздочкой ожидаемый для меня результат.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

А, понятно, это потому я что я перешёл со звёздочки на собаку. Пишут что так работает лучше, но в чём разница я пока не понял.

Ну как можно в одной строчке написать, что понятно и не понял?

vodz ★★★★★
()
Ответ на: комментарий от vodz

Раньше использовал ${a[*]}. И в этом случае кавычки работают ожидаемо.

Недавно прочитал про ${a[@]} и что это работает лучше. Раз так пишут значит так и надо делать.

Но в чём разница между ними пока непонятно.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

Недавно прочитал про ${a[@]} и что это работает лучше. Раз так пишут значит так и надо делать.

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

vodz ★★★★★
()
Ответ на: комментарий от sin_a
The only difference between @ and * is when the form ${my_array[x]} is surrounded with double-quotes. In this case, * expands to a single word where array elements are separated with space. @ expands each array element to a separate word. This is especially important when using the form to illiterate through array elements.
Entmatix
()
Ответ на: комментарий от vodz

https://www.opennet.ru/docs/RUS/bash_scripting_guide/c3270.html

$*
Все аргументы в виде одной строки (слова)
$@
То же самое, что и $*, но при этом каждый параметр представлен как отдельная строка (слово), т.е. параметры не подвергаются какой либо интерпретации.

Это про параметры.

https://www.opennet.ru/docs/RUS/bash_scripting_guide/c12790.html

# Переменная «@» позволяет «разбивать» строку в кавычках на отдельные слова
#+ (выделяются слова, разделенные пробелами).

Это про массивы.

Здесь одно и то же или это разные механизмы?

sin_a ★★★★★
() автор топика
Ответ на: комментарий от gremlin_the_red

Могу только присоединиться к совету выше о чтении документации.

А я присоединюсь к совету использовать нормальный и очевидный язык скриптового программирования, вместо ковярния этих кавычечных нюансов 80-ых годов.

Вот уже два часа ТС ковыряется с этими дурацкими кавычками, звёздочками и собачками, когда на другом языке он бы уже сделал всю работу и сделал бы это приемлимо и поддерживаемо. А не так, что его скрипт с кавычками отправится на свалку через некоторое время.

Меньше кода на Bash – чище мир.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Да, вот например можно вспомнить питон, недавно я имел дело с питоном, помню, очень понравилось.

Там если нужно вызвать системную команду то с этим всё просто. Сначала нужно импортировать какую-то библиотеку. Потом нужно неким образом правильно передать системную команду питоновской команде из этой библиотеки. При этом нужно правильно разделить саму команду и параметры этой команды. После этого, если получилось запустить системную команду, нужно неким образом правильно получить результат действия. Раздельно, конечно, получить стандартный вывод и вывод ошибок. Вот не помню только что с кодом возврата, но скорее всего тоже всё просто. Сразу видно, для умных людей, не для кого попало. Серьёзный подход.

Не то что в старом примитивном баше, просто запускай и всё, так то любой дурак сможет.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

Когда у тебя вместо по одной цифре в массиве будет массив строк, которые содержат в себе пробелы, вот тогда приходит понимание, что собачку ставить лучшее.
Если коротко, то строка с пробелами будет как строка с пробелами, а не разбитые на строки слова.
Цифры плохой пример.
Учись на строках. Много приключений гарантировано.

TomBOY ★★
()

В баше внутри все довольно специфчески с за пахом говнеца сделано

# Выражение вида
for i in "${arr[@]}"; do

done

# ТУПА разворачивается в такое
for i in "element1" "element2" "element3" ...; do

done
tz4678_2
()

А насчет нужности кавычек, то все зависит от версии БРНОХЕЛЛА:

~ 
➜ arr=(foo "bar baz")                 

# В Z shell все работает как надо
~ 
➜ for i in ${arr[@]}; do echo $i; done
foo
bar baz

# А вот Bash - петух
~ 
➜ bash
[sergey@sergey-arch ~]$ arr=(foo "bar baz")
[sergey@sergey-arch ~]$ for i in ${arr[@]}; do echo $i; done
foo
bar
baz
tz4678_2
()
Ответ на: комментарий от sin_a

Здесь одно и то же или это разные механизмы?

Да, изначально в shell-ах был только один встроенный массив — массив аргументов, потом добавили массивы вообще, но снтаксис по возможности сохранили.

Вы можете толком сказать, что вы понять то не можете? Я же дал простой пример в первом коменте. Даже без документации можно понять разницу. Первый цикл будет получать все имена файлов, удовлетворяющих списку масок в массиве. Второй - выведет сам список масок, а не файлов по ним. И то и другое — нужное, а не «лучше». А "${a[*]}" сконстрирует ровно одну строку с разделителями из первого символа $IFS и потому в цикл пихать с кавычками бессмысленно.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от vodz

Ну, легко видна разница когда много имеешь дела непосредственно с материалом. Когда касаешься инструмента эпизодически, понимать его надо но в целом достаточно границ применимости.

В силу того, что я не очень активно использую shell – стараюсь не использовать сложных для понимания конструкций. Сейчас проверил, в этом примере при наличии файла с пробелом он обрабатывается нормально. Но в подобном случае я предпочту перебирать файлы по одному. Здесь смешиваются вещи разного уровня, синтаксис с семантикой, и нужно достаточно внимания чтобы это контролировать. К сожалению shell действительно плохо подходит при усложнении скрипта, @EXL прав (нет, @EXL, спасибо, можешь не беспокоиться, скрипт давно написан и здесь у меня вопрос общего характера).

В общем наверно можно сказать так. Не понимаю какую конкретно задачу решали введением символа «@» вместо «*». Поняв какую решали задачу можно понять и границу применимости.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

Не понимаю какую конкретно задачу решали введением символа «@» вместо «*».

Да сколько ж можно, нет там никакого «вместо»! Была задача — сформировать список аргументов/значений для перебора циклом с возможностью или без интерпретирования каждого аргумента, ведь и то и другое может быть нужно в каждом конкретном месте.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Если «@» появился позже (этого я не знаю, предполагаю) то он заменил «*» в некоторых случаях, когда этот символ действовал не так как надо. А заменил – значит «вместо» в данных случаях.

В общем вроде понятно. Символ ввели именно для массивов (в начале массива аргументов а затем и других). Поэтому массив взятый в кавычки не превращается в тыкву и вероятно я столкнусь ещё с какими нибудь особенностями. А «*» , если я не планирую использовать маски в качестве переменных, или что нибудь подобное, мне следует просто избегать.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

Если «@» появился позже (этого я не знаю, предполагаю) то он заменил «*» в некоторых случаях, когда этот символ действовал не так как надо. А заменил – значит «вместо» в данных случаях.

Вы утомляете. В каждом коменте говорю, что ничего не заменял, а добавлен к. И почти сразу.

А «*» , если я не планирую использовать маски в качестве переменных

Какие такие звездочки в качестве переменных? Хотите помощи — выражайтесь понятно. В shell-ах количетсво спецсимволов достаточно, начиная с пробела, звездочка дана только в качестве наглядного примера без выкрутасов с созданием имен с пробелами и прочих пугающих значков.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Ну это вопрос терминологии. Почти сразу значит позже. Пока его не было обходились только звёздочкой. Если существовали случаи когда ранее использовалась звёздочка а стала собака, то… Впрочем, это действительно неважно.

Да, действительно дело не в звёздочке. А в том, что в строке всегда может встретиться символ, который создаст неоднозначную ситуацию и возможно всё сломает. Разделитель полей, перевод строки, двоеточие, точка с запятой, скобки всевозможные. Даже думать не хочу какой символ в каком случае может дать побочный эффект. Просто принял что кавычки нужно использовать всегда, кроме случаев когда действительно необходимо использовать строку без кавычек.

А «*» , если я не планирую использовать маски в качестве переменных  

Какие такие звездочки в качестве переменных?

Имел в виду, если в качестве значения элементов массивов я не планирую использовать потенциально проблемные символы, например маски файлов, то мне следует избегать формы записи «${массив[*]}» и следует использовать «${массив[@]}», как то так.

Хотя правильнее наверно так: вообще не вижу случая, когда мне могла бы понадобиться форма «${массив[*]}».

В общем спасибо, вроде в целом всё более-менее ясно.

sin_a ★★★★★
() автор топика