Может кто то подскажет в каких случаях массивы облегчают жизнь.
bash array подскажите
Модераторы: /dev/random, Модераторы разделов
-
LittleJohn
- Сообщения: 5
bash array подскажите
Так привык не пользоваться массивами в bash, что теперь не могу и придумать где их использовать
Может кто то подскажет в каких случаях массивы облегчают жизнь.
Может кто то подскажет в каких случаях массивы облегчают жизнь.
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
При универсальной обработке произвольных аргументов. Для примера, попробуйте написать скрипт следующего вида:LittleJohn писал(а): ↑17.01.2011 19:50Может кто то подскажет в каких случаях массивы облегчают жизнь.
Код: Выделить всё
Usage: script [options] [--] command [args]
Options:
-s Run command under sudo
-t Run command under strace
-u USER Run with this user's rights. Implies sudo.
Examples:
script echo 123
Just executes `echo 123`.
script -s echo 123
Executes `sudo echo 123`.
script -u somebody -t echo 123
Executes `sudo -u somebody strace echo 123`.Мои розовые очки
-
t.t
- Бывший модератор
- Сообщения: 7390
- Статус: думающий о вечном
- ОС: Debian, LMDE
Re: bash array подскажите
В целом пример хороший, но именно для _работы_ с массивами можно добавить вариант, где нужно, скажем, перетасовать аргументы местами. А не просто один раз вставить "$@". (:watashiwa_daredeska писал(а): ↑17.01.2011 20:14При универсальной обработке произвольных аргументов. Для примера, попробуйте написать скрипт следующего вида:LittleJohn писал(а): ↑17.01.2011 19:50Может кто то подскажет в каких случаях массивы облегчают жизнь.
Соответственно, штуковина должна работать с любыми аргументами, включая содержащие символы с кодами 1..32, кавычками и прочими спец. символами shell.Код: Выделить всё
Usage: script [options] [--] command [args] Options: -s Run command under sudo -t Run command under strace -u USER Run with this user's rights. Implies sudo. Examples: script echo 123 Just executes `echo 123`. script -s echo 123 Executes `sudo echo 123`. script -u somebody -t echo 123 Executes `sudo -u somebody strace echo 123`.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
-
sash-kan
- Администратор
- Сообщения: 13939
- Статус: oel ngati kameie
- ОС: GNU
Re: bash array подскажите
такой подойдёт?watashiwa_darede... писал(а): ↑17.01.2011 20:14Для примера, попробуйте написать скрипт следующего вида
Код: Выделить всё
#!/bin/bash
unset sudo_c user_c
while getopts 'su:' flag
do
case "$flag" in
"s") sudo_c="sudo";;
"u") if [ ! "$user_c" ]
then sudo_c="sudo"; user_c="-u $OPTARG"
fi;;
esac
done
shift $((OPTIND-1))
echo $sudo_c $user_c "$@"$ ./script -s -u root -s a$(echo -e '\0001')b
sudo -u root ab
$ ./script -s -u root -s a$(echo -e '\0001')b | hd
00000000 73 75 64 6f 20 2d 75 20 72 6f 6f 74 20 61 01 62 |sudo -u root a.b|
00000010 0a |.|
00000011
после замены echo на eval:
$ ./script -s -u root -s a$(echo -e '\0001')b
sudo: ab: command not found
гхм. при вводе команды текущий шелл влезет грязными лапками и сделает подстановки. есть вариант, как это можно обойти программно?
p.s. самое главное-то: а зачем массивы в таком скрипте?
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
при сбоях форума см.блог
-
ZyX
- Сообщения: 355
- ОС: Gentoo
Re: bash array подскажите
sash-kan писал(а): ↑17.01.2011 23:18такой подойдёт?watashiwa_darede... писал(а): ↑17.01.2011 20:14Для примера, попробуйте написать скрипт следующего видав последней строке стоит echo (а не eval) для тестов:Код: Выделить всё
#!/bin/bash unset sudo_c user_c while getopts 'su:' flag do case "$flag" in "s") sudo_c="sudo";; "u") if [ ! "$user_c" ] then sudo_c="sudo"; user_c="-u $OPTARG" fi;; esac done shift $((OPTIND-1)) echo $sudo_c $user_c "$@"
$ ./script -s -u root -s a$(echo -e '\0001')b
sudo -u root ab
$ ./script -s -u root -s a$(echo -e '\0001')b | hd
00000000 73 75 64 6f 20 2d 75 20 72 6f 6f 74 20 61 01 62 |sudo -u root a.b|
00000010 0a |.|
00000011
после замены echo на eval:
$ ./script -s -u root -s a$(echo -e '\0001')b
sudo: ab: command not found
гхм. при вводе команды текущий шелл влезет грязными лапками и сделает подстановки. есть вариант, как это можно обойти программно?
И чем это мешает? vim +'set ft=vim' a\ b\"c, screen -m vim +'set ft=vim' a\ b\"c и exec vim +'set ft=vim' a\ b\"c работают одиноково хорошо.
// В zsh можно для этого переопределить widget accept-line.
Если массивы там не нужны, уберите $@.
Кстати, напишите на bash скрипт, который принимает такие же аргумента, как и zip, но создаёт .tar.gz архив. Так как это очень долго, то можно оставить только аргументы -d, -g, -x, -i, -O, -nw, -q, -v, -y, -r при том, что везде, где могут быть спецсимволы, они должны корректно обрабатываться. Также можно забыть о длинных формах и -{key}{value}, оставив только -{key} {value}. Без создания новых массивов. Считать, что tar использует те же регулярные выражения, что и zip. Потом сравним версию без массивов и с ними.
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
А eval там вообще нельзя, ибо он непоправимо покорёжит "$@". Надо просто $sudo_c $user_c "$@".
В целом пример плохой, как показало решение sash-kan. Тут спасает то, что sudo, username и strace не содержат «нехороших» символов по определению. Если задача в склеивании большой команды из нескольких кусочков, которые задаются пользователем и могут содержать гадости, то всё становится хуже. Просто a la $sudo_c без кавычек уже не напишешь, а "$sudo_c" съедает деление на отдельные токены, а eval "$sudo_c" творит страшное без дополнительного правильного закавычивания того, что внутри. Иногда можно, конечно играть во что-нибудь вроде set -- cmd "arg 1" "arg 2" "$@", но не всегда.
При вводе можно закавычить. Я имел в виду, что если я ввел башевское $'xyz\n$(cat /etc/passwd)\n\e[31m', то оно должно таким и остаться, вместе со всеми переводами строк, знаками доллара и пр., а не развернуться где-то в потрохах скрипта.
Ещё один use case вспомнился, где мне array'и помогли. Есть набор строк. «Нехороших» с т.з. шелла (пробелы, кавычки и т.п.). Нужно по ним прогнать for.
Мои розовые очки
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
Хуже того, $ ./script -s -u root -s 'a$(echo -e '\0001')b' выдаст то же самое, что уже не правильно. Именно потому, что eval.
Мои розовые очки
-
t.t
- Бывший модератор
- Сообщения: 7390
- Статус: думающий о вечном
- ОС: Debian, LMDE
Re: bash array подскажите
Вот тут не совсем понял. Какое деление съедают кавычки? Пробелами? То, что попадёт в массив, к этому времени уже будет разделено.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
Да.
Если без массивов решать задачу. Массив-то как раз эту проблему позволяет решить легко.
Мои розовые очки
-
t.t
- Бывший модератор
- Сообщения: 7390
- Статус: думающий о вечном
- ОС: Debian, LMDE
Re: bash array подскажите
А, тогда понял. (: Да, без массивов та ещё работа получится. Не зря ведь, в частности, упомянутый $@ встречается в скриптах гораздо чаще, чем $*.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
-
sash-kan
- Администратор
- Сообщения: 13939
- Статус: oel ngati kameie
- ОС: GNU
Re: bash array подскажите
отличное предложение. «доберитесь до информации, хранящейся _только_ в массиве, не используя массива»
ну что ж, попробую «спеть о том же самом в несколько более сложных словах».
требуется, чтобы команда
$ ./script vim +'set ft=vim' a\ b\"c
запускала vim для редактирования файл «a b"c», установив filetype в значением "vim" и при этом не использовался (наверно, единственный встроенный) массив $@? извольте:
Код: Выделить всё
#!/bin/bash
c="$1"
shift
while [ "$1" ]; do
c="$c '$1'"
shift
done
eval $cПисать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
при сбоях форума см.блог
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
Не верю! c="$c '$1'" совершенно недостаточно, чтобы одинарная кавычка из $1 корректно обрабатывалась потом в eval.
Нужно чуть сложнее: c="$c '$(echo "$1" | sed "s/'/'\\\''/g")'" Однако, никто не говорит, что массивы позволяют что-то, чего нельзя без них. Ты же понимаешь: тьюринг-полный и т.д. и т.п. Но некоторые вещи с массивами делать проще и читать потом легче, чем вот ту фигатень с sed'ом.
Мои розовые очки
-
t.t
- Бывший модератор
- Сообщения: 7390
- Статус: думающий о вечном
- ОС: Debian, LMDE
Re: bash array подскажите
Собственно, я к тому и говорил: пример твой вовсе не плохой, т.к. преимущество использования массивов демонстрирует. По коду sash-kan см. замечание ZyX: массив у него всё-таки есть.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
-
t.t
- Бывший модератор
- Сообщения: 7390
- Статус: думающий о вечном
- ОС: Debian, LMDE
Re: bash array подскажите
С чего вдруг «только»? Она и в строке хранится: $*.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
-
/dev/random
- Администратор
- Сообщения: 5456
- ОС: Gentoo
-
t.t
- Бывший модератор
- Сообщения: 7390
- Статус: думающий о вечном
- ОС: Debian, LMDE
Re: bash array подскажите
Кстати, в ABS-е обычно неплохие примеры. Может и по массивам подойдут?
http://tldp.org/LDP/abs/html/arrays.html
http://rus-linux.net/MyLDP/BOOKS/abs-guide...ook.html#ARRAYS
http://tldp.org/LDP/abs/html/arrays.html
http://rus-linux.net/MyLDP/BOOKS/abs-guide...ook.html#ARRAYS
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
-
sash-kan
- Администратор
- Сообщения: 13939
- Статус: oel ngati kameie
- ОС: GNU
Re: bash array подскажите
спасибо. а то сбивают с толку, понимаешь…/dev/random писал(а): ↑18.01.2011 10:53
$@ - не массив, а просто подстановка в строку всех аргументов скрипта/функции, с корректным делением на аргументы.
И, кстати, в POSIX массивов нет, а $@ - есть.
в том случае когда у вас любимый стиль такой.LittleJohn писал(а): ↑17.01.2011 19:50Может кто то подскажет в каких случаях массивы облегчают жизнь.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
при сбоях форума см.блог
-
sash-kan
- Администратор
- Сообщения: 13939
- Статус: oel ngati kameie
- ОС: GNU
Re: bash array подскажите
кстати, очень хотелось бы увидеть пример более простой и легче читаемой работы с переменной $@..watashiwa_daredeska писал(а): ↑18.01.2011 04:37Не верю! c="$c '$1'" совершенно недостаточно, чтобы одинарная кавычка из $1 корректно обрабатывалась потом в eval.
Нужно чуть сложнее: c="$c '$(echo "$1" | sed "s/'/'\\\''/g")'" Однако, никто не говорит, что массивы позволяют что-то, чего нельзя без них. Ты же понимаешь: тьюринг-полный и т.д. и т.п. Но некоторые вещи с массивами делать проще и читать потом легче, чем вот ту фигатень с sed'ом.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
при сбоях форума см.блог
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
-
sash-kan
- Администратор
- Сообщения: 13939
- Статус: oel ngati kameie
- ОС: GNU
Re: bash array подскажите
ну, я вот это попробовал написать без массивов:
watashiwa_darede... писал(а): ↑17.01.2011 20:14Для примера, попробуйте написать скрипт следующего вида
был раскритикован за некорректность. сделал по-другому. опять раскритикован. с добавкой про сложность и нечитабельность.
я совершенно не против критики и безоговорочно признаю её.
только прошу — покажи, пожалуйста, как реализовать твой же пример проще и нагляднее.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
при сбоях форума см.блог
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
Слегка модифицированный пример с двумя возможными префиксными командами и аргументами к ним в свободной форме:
Код: Выделить всё
#!/bin/bash
# wrapper.sh без массивов
quote() {
echo -n "'"
echo -n "$1" | sed "s/'/'\\\''/g"
echo -n "'"
}
unset prefix_a prefix_b command
eval "set -- $(getopt -o +a:b: -- "$@")"
while :; do
case "$1" in
-a)
prefix_a="prefix_a $(quote "$2")"
shift
;;
-b)
prefix_b="prefix_b $(quote "$2")"
shift
;;
--)
shift
break
;;
esac
shift
done
command="$prefix_a $prefix_b"
for arg; do
command="$command $(quote "$arg")"
done
eval "args $command"Код: Выделить всё
#!/bin/bash
# wrapper.sh с массивами
unset prefix_a prefix_b
eval "set -- $(getopt -o +a:b: -- "$@")"
while :; do
case "$1" in
-a)
prefix_a=(prefix_a "$2")
shift
;;
-b)
prefix_b=(prefix_b "$2")
shift
;;
--)
shift
break
;;
esac
shift
done
args "${prefix_a[@]}" "${prefix_b[@]}" "$@"Код: Выделить всё
#!/bin/sh
# args
i=0
while [ $# -gt 0 ]; do
echo "[$i]: '$1'"
shift
i=$((i+1))
doneПримеры:
user@localhost
~$ ./wrapper.sh cmd
[0]: 'cmd'
~$ ./wrapper.sh $'multiline\ncmd'
[0]: 'multiline
cmd'
~$ ./wrapper.sh -a A cmd
[0]: 'prefix_a'
[1]: 'A'
[2]: 'cmd'
~$ ./wrapper.sh -a A\'B\ C$'\n'D cmd
[0]: 'prefix_a'
[1]: 'A'B C
D'
[2]: 'cmd'
~$ ./wrapper.sh -a A\'B\ C$'\n'D -b E\'F\ G$'\n'H cmd
[0]: 'prefix_a'
[1]: 'A'B C
D'
[2]: 'prefix_b'
[3]: 'E'F G
H'
[4]: 'cmd'Очевидно, что если убрать args, то будут выполняться выводимые команды в точности.
Вот как-то так.
Мои розовые очки
-
sash-kan
- Администратор
- Сообщения: 13939
- Статус: oel ngati kameie
- ОС: GNU
Re: bash array подскажите
watashiwa_darede...
или я чего-то не понимаю, или не вижу, в каком месте тут наличествует «простота и легкочитабельность». да и вообще кардинальных отличий от написанного мною что-то тоже не улавливаю.
ткни меня, пожалуйста, носом в то место, где «некоторые вещи с массивами делать проще и читать потом легче, чем вот ту фигатень с sed'ом».
или я чего-то не понимаю, или не вижу, в каком месте тут наличествует «простота и легкочитабельность». да и вообще кардинальных отличий от написанного мною что-то тоже не улавливаю.
ткни меня, пожалуйста, носом в то место, где «некоторые вещи с массивами делать проще и читать потом легче, чем вот ту фигатень с sed'ом».
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
при сбоях форума см.блог
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
Прелесть в том, что без массивов нужно квотировать явно вручную один и только один раз, ни на секунду не забывая, что ты уже отквотировал ранее, а что еще нет, иначе получится полная фигня. И в результате, без использования массивов появляются всякие прелести, вроде того цикла по всем аргументам в конце. И это еще очень простой как топор случай, где всё очень легко. Если появится хоть какая более-менее сложная логика обработки и преобразования аргументов, начнется полный ахтунг с этим квотированием. А вот с массивами всё просто.
Если отбросить парсинг опций, то в скрипте с использованием массивов остается ровно одна строчка: та, которая последняя, а в скрипте без массивов еще функция и цикл, который надо не забыть, иначе всё пропало.
Твои примеры, если без изменений, не будет работать с аргументами из моих примеров.
Мои розовые очки
-
sash-kan
- Администратор
- Сообщения: 13939
- Статус: oel ngati kameie
- ОС: GNU
Re: bash array подскажите
то же самое останется. ведь $@ — это не массив.watashiwa_darede... писал(а): ↑19.01.2011 13:44Если отбросить парсинг опций, то в скрипте с использованием массивов остается ровно одна строчка: та, которая последняя, а в скрипте без массивов еще функция и цикл, который надо не забыть, иначе всё пропало.
при разборе аргументов — да, понадобится эскейпить кавычки при разделении на токены. других преимуществ не наблюдаю.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
при сбоях форума см.блог
-
t.t
- Бывший модератор
- Сообщения: 7390
- Статус: думающий о вечном
- ОС: Debian, LMDE
Re: bash array подскажите
Он про свои два скрипта, а не про твой. Или я тебя неправильно понял?sash-kan писал(а): ↑19.01.2011 21:36то же самое останется. ведь $@ — это не массив.watashiwa_darede... писал(а): ↑19.01.2011 13:44Если отбросить парсинг опций, то в скрипте с использованием массивов остается ровно одна строчка: та, которая последняя, а в скрипте без массивов еще функция и цикл, который надо не забыть, иначе всё пропало.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
-
sash-kan
- Администратор
- Сообщения: 13939
- Статус: oel ngati kameie
- ОС: GNU
Re: bash array подскажите
в своём первом скрипте wd зачем-то усложнил конструкцию, организовав цикл по списку аргументов. естественно, это не нужно. можно напрямую взять значение специальной переменной $@. ведь это не array, а специальная переменная (rtmb → read the man bash).t.t писал(а): ↑19.01.2011 22:20Он про свои два скрипта, а не про твой. Или я тебя неправильно понял?sash-kan писал(а): ↑19.01.2011 21:36то же самое останется. ведь $@ — это не массив.watashiwa_darede... писал(а): ↑19.01.2011 13:44Если отбросить парсинг опций, то в скрипте с использованием массивов остается ровно одна строчка: та, которая последняя, а в скрипте без массивов еще функция и цикл, который надо не забыть, иначе всё пропало.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
при сбоях форума см.блог
-
drBatty
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
- ОС: Slackware-current
Re: bash array подскажите
LittleJohn писал(а): ↑17.01.2011 19:50Может кто то подскажет в каких случаях массивы облегчают жизнь.
вот как использует массивы Патрег:
Код: Выделить всё
# Config information for eth0:
IPADDR[0]=""
NETMASK[0]=""
USE_DHCP[0]="yes"
DHCP_HOSTNAME[0]=""
DHCP_KEEPRESOLV[0]="yes"
# Config information for eth1:
IPADDR[1]="172.16.1.1"
NETMASK[1]="255.255.255.0"
USE_DHCP[1]="no"
DHCP_HOSTNAME[1]=""
DEBUG_ETH_UP[1]="yes"тут каждый сетевой интерфейс описывается одним эл-том массива, а потом они поднимаются единой функцией, в цикле.
Код: Выделить всё
# Function to start the network:
start() {
lo_up
for i in ${IFNAME[@]}; do
if_up $i
done
gateway_up
if [ -x /etc/rc.d/rc.dhcpd ]; then
/etc/rc.d/rc.dhcpd start
fi
}это позволяет удобно задавать параметры для каждого интерфейса. Альтернативный вариант с sed был-бы более неуклюж в данном случае.
ЗЫЖ а про кавычки вы зря - используйте sed-скрипты, в которых можно юзать любые кавычки.
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
Нельзя. Потому что для eval нужен дополнительный уровень квотирования, а без eval аргументы в общем виде тоже не обработать.
Мои розовые очки
-
/dev/random
- Администратор
- Сообщения: 5456
- ОС: Gentoo
Re: bash array подскажите
watashiwa_daredeska писал(а): ↑20.01.2011 14:47а без eval аргументы в общем виде тоже не обработать.
Почему это?
[ -n "$foo" ] && set -- foo "$foo" "$@"
[ -n "$bar" ] && set -- bar "$bar" "$@"
script "$@"
-
watashiwa_daredeska
- Бывший модератор
- Сообщения: 4038
- Статус: Искусственный интеллект (pre-alpha)
- ОС: Debian GNU/Linux
Re: bash array подскажите
/dev/random писал(а): ↑20.01.2011 14:54Почему это?
[ -n "$foo" ] && set -- foo "$foo" "$@"
[ -n "$bar" ] && set -- bar "$bar" "$@"
script "$@"
watashiwa_darede... писал(а): ↑17.01.2011 23:59Иногда можно, конечно играть во что-нибудь вроде set -- cmd "arg 1" "arg 2" "$@", но не всегда.
Мои розовые очки