Re: Подстановка переменн ого числа аргументов
On 28.10.2010 15:14, Serhiy Storchaka wrote: Здравствуйте. Прошу прощения за такой элементарный и не совсем тематический вопрос, но это наиболее компетентная группа, которую я сейчас читаю. Задача. В зависимости от некоторых условий необходимо вызвать команду с дополнительными аргументами или без них. Например: if somecheck then OPTS="--foo $FOO" else OPTS="" fi bar -ziq $OPTS bla-bla-bla Проблема в том, что $FOO может быть пустым (тогда подставится лишь один аргумент --foo) или содержать пробелы (тогда подставится больше двух аргументов). Можно, конечно, написать: if somecheck then bar -ziq --foo "$FOO" bla-bla-bla else bar -ziq bla-bla-bla fi И всё будет работать как надо. Но хотелось бы избежать дублирования, постоянные аргументы вызова могут быть громоздкими. Не говоря уж о том, что если будет несколько условий, код разрастётся в геометрической прогрессии. Как быть? Решение не красивое из-за примитивности самого shell-языка: $ var="--opt arg 'arg-part1 arg2-part2'" $ printarg $var "printarg" "--opt" "arg" "'arg-part1" "arg2-part2'" $ sh -c "printarg $var" "printarg" "--opt" "arg" "arg-part1 arg2-part2" Еще ограничение POSIX shell: bash# foo=bar bash# bar=xxx bash# echo ${${foo}} bash: ${${foo}}: bad substitution или bash# foo1=xxx bash# foo2=yyy bash# var=1 bash# echo ${foo${var}} bash: ${foo${var}}: bad substitution Для сравнения GNU Make раскрывает "по максимуму": foo=bar bar=xxx $(error $($(foo))) $ make Makefile:3: *** xxx. Останов. Интересно почитать про особенную переменную "$@" в двойных кавычках. Нечто аналогичное делает утилита pathsearch, вот кусочек от туда: [ -z "$_var" ] && _var=PATH [ -z "$_delim" ] && _delim=":" IFS="$_delim" find=no for token in `sh -c "echo \$""$_var"`; do## здесь интересно if [ -e "$token/$_pattern" ]; then find=yes echo "$token/$_pattern" continue fi if ls "$token"/$_pattern 2>/dev/null; then find=yes fi done [ $find = yes ] && exit 0 || exit 1 Вы можете передать имя переменной окружения в качестве аргумента утилите, но раскрыть значение имени хранимого в параметре может следующий shell. -- С уважением, Александр Гавенко. -- To UNSUBSCRIBE, email to debian-russian-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/4cc97cc5.1010...@bifit.com.ua
Re: Подстановка переменн ого числа аргументов
On 28.10.2010 16:20, Victor Wagner wrote: On 2010.10.28 at 15:14:51 +0300, Serhiy Storchaka wrote: Здравствуйте. Прошу прощения за такой элементарный и не совсем тематический вопрос, но это наиболее компетентная группа, которую я сейчас читаю. Задача. В зависимости от некоторых условий необходимо вызвать команду с дополнительными аргументами или без них. Например: if somecheck then OPTS="--foo $FOO" else OPTS="" fi bar -ziq $OPTS bla-bla-bla Проблема в том, что $FOO может быть пустым (тогда подставится лишь один аргумент --foo) или содержать пробелы (тогда подставится больше двух аргументов). Можно, конечно, написать: if somecheck then bar -ziq --foo "$FOO" bla-bla-bla else bar -ziq bla-bla-bla fi И всё будет работать как надо. Но хотелось бы избежать дублирования, постоянные аргументы вызова могут быть громоздкими. Не говоря уж о том, что если будет несколько условий, код разрастётся в геометрической прогрессии. Как быть? Ну во-первых, можно подумать о подстановках вида ${FOO:+--foo "${FOO}"} Это на тот случай если задача ставится так "Если перемная FOO не пуста, подставляем ключик --foo "$FOO", иначе не делаем ничего. Иногда это делает код читабельнее. Во-вторых, можно подумать об использовании команды set, которая позволит засунуть нужные параметры на место аргументов шелловского скрипта. И потом подставлять через "$@" - c cохранением разбиения на аргументы. Интересная идея, правда не всегда получается: bash# set arg "arg-part1 arg-part2" bash# printarg "$@" "printarg" "arg" "arg-part1 arg-part2" bash# var='arg "arg-part1 arg-part2"' bash# set $var bash# printarg "$@"## плохо "printarg" "arg" ""arg-part1" "arg-part2"" В-третьих, почитать доку на специфические возможности используемого шелла. Может быть в bash или zsh есть специальные удобные средства для этой цели. Кто знает отпишите пожалуста! В-четвертых, можно аккуратно квотить дважды. В смысле OPTS="--foo \"\$FOO\"" или OPTS="--foo \"$FOO\"" (почувстуйте разницу между этими двумя вариантами. Не до конца работает: $ var="--opt arg 'arg-part1 arg2-part2'" $ printarg $var "printarg" "--opt" "arg" "'arg-part1" "arg2-part2'" Что бы заставить работать надо: $ sh -c "printarg $var" "printarg" "--opt" "arg" "arg-part1 arg2-part2" -- С уважением, Александр Гавенко. -- To UNSUBSCRIBE, email to debian-russian-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/4cc980bc.6060...@bifit.com.ua
Re: Подстановка переменн ого числа аргументов
On 28.10.2010 19:17, Serhiy Storchaka wrote: Peter Pentchev wrote: On Thu, Oct 28, 2010 at 05:44:31PM +0300, Serhiy Storchaka wrote: А printarg -- это откуда? Если не ошибаюсь, Олександр имеет ввиду чего-то вроде: #!/bin/sh # # This trivial utility is hereby placed into the public domain. while [ "$#" -gt 0 ]; do printf '"%s"\n' "$1" shift done (только-что написал, может, есть какие-то баги :) Ну зачем же так сурово, можно: for a in "$@" do printf '"%s"\n' "$a" done Я сперва думал, может какая-то встроенная команда для отладки в последнем баше появилась. Или из какого-нибудь пакета shell-misc, содержащего ещё несколько полезных скриптов. Так, только на Си. Cygwin портит аргументы после вызова программ зависимых от cygwin1.dll (поведение зависит от значения перем. огруж. CYGWIN), вроде как до main. Нужно было собрать альтернативным компилятором, что бы узнать что же там по настоящему передается. -- С уважением, Александр Гавенко. -- To UNSUBSCRIBE, email to debian-russian-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/4cca6fa8.1040...@bifit.com.ua
Re: Подстановка переменн ого числа аргументов
On 29.10.2010 11:16, Serhiy Storchaka wrote: Oleksandr Gavenko wrote: Cygwin портит аргументы после вызова программ зависимых от cygwin1.dll (поведение зависит от значения перем. огруж. CYGWIN), вроде как до main. Это вынужденные костыли, не нужно винить Cygwin за его помощь убогим. Любая программа под WinDos вынуждена сама портить свои аргументы. Нужно было собрать альтернативным компилятором, что бы узнать что же там по настоящему передается. Если запустите не через bash#, а через C:\> -- результат будет другим. Не критикую Cygwin. Нужно было побороть "умность" Cygwin. http://thread.gmane.org/gmane.emacs.help/73810 http://thread.gmane.org/gmane.os.cygwin/122538 Теперь если CYGWIN=noglob из argv удаляются '\', а если убрать 'noglob', то из argv удаляются '{}'. В любом случае плохо, надо дебажить. Но мы же не об этом )) -- С уважением, Александр Гавенко. -- To UNSUBSCRIBE, email to debian-russian-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/4cca92a4.8020...@bifit.com.ua