У меня есть функция Bash, чтобы установить, $PATH
как это -
assign-path()
{
str=$1
# if the $PATH is empty, assign it directly.
if [ -z $PATH ]; then
PATH=$str;
# if the $PATH does not contain the substring, append it with ':'.
elif [[ $PATH != *$str* ]]; then
PATH=$PATH:$str;
fi
}
Но проблема в том, что мне нужно написать разные функции для разных переменных (например, другую функцию для $CLASSPATH
подобных assign-classpath()
и т. Д.). Я не смог найти способ передать аргумент в функцию bash, чтобы я мог получить к нему доступ по ссылке.
Было бы лучше, если бы у меня было что-то вроде -
assign( bigstr, substr )
{
if [ -z bigstr ]; then
bigstr=substr;
elif [[ bigstr != *str* ]]; then
bigstr=bigstr:substr;
fi
}
Есть идеи, как добиться чего-то похожего в bash?
bash
bash-script
ramgorur
источник
источник
assign-path /abc
не будет добавлять/abc
к PATH , если $ PATH уже содержит/abc/def
,/abcd
, и/def/abc
т.д. Особенно вы не можете добавить ,/bin
если PATH уже содержит/usr/bin
.$PATH
и свести на нет теста на ваши аргументы , как:add=/bin dir=/usr/bin ; [ -z "${dir%"$add"}" ] || dir="${dir}:${add}"
. В своем ответе я делаю это таким образом, используя столько аргументов, сколько вы хотите использоватьIFS=:
.$PATH
? и добавьте каталог,$PATH
если его там еще нет (на Super User ).Ответы:
В
bash
вы можете использовать${!varname}
для раскрытия переменной, на которую ссылается содержимое другой. Например:Со страницы руководства:
Кроме того
eval
, вы можете использовать переменную, на которую ссылается содержимое (без опасностей )declare
. Например:Таким образом, вы могли бы написать свою функцию следующим образом ( будьте осторожны, потому что если вы используете
declare
функцию, вы должны указать,-g
или переменная будет локальной):И используйте это как:
Обратите внимание, что я также исправил ошибку, из-за которой, если
substr
она уже является подстрокой одного из членов, разделенных двоеточиямиbigstr
, но не является собственным, то она не будет добавлена. Например, это позволит добавить/bin
вPATH
переменную, уже содержащую/usr/bin
. Он используетextglob
наборы, чтобы соответствовать либо началу / концу строки, либо двоеточию, чем чему-либо еще. Безextglob
, альтернатива будет:источник
-g
indeclare
недоступен в более старой версии bash, есть ли способ сделать его обратно совместимым?export
чтобы поместить его в свою среду (риск перезаписать что-то важное) илиeval
(различные вопросы, включая безопасность, если вы не будете осторожны). При использованииeval
вы должны быть в порядке, если вы делаете это какeval "$target=\$substr"
. Если вы забудете об этом\
, он потенциально выполнит команду, если в содержимом будет пробелsubstr
.Новое в bash 4.3, это
-n
опцияdeclare
&local
:Это распечатывает
hello, world
.источник
Вы можете использовать
eval
для установки параметра. Описание этой команды можно найти здесь . Следующее использованиеeval
неверно:Что касается дополнительной оценки
eval
, следует ли вам использоватьПроверьте результаты использования этих функций:
Но вы можете достичь своей цели без использования
eval
. Я предпочитаю этот способ, который является более простым.Следующая функция делает замену правильным образом (надеюсь)
Проверьте следующий вывод
Теперь вы можете использовать
augment
функцию следующим образом для установки переменной:источник
v='echo "OHNO!" ; var' ; l=val ; eval $v='$l'
- выдает «OHNO!» Перед назначением переменной. Вы можете «$ {v ## * [;« $ IFS »]} = '$ l'", чтобы гарантировать, что строка не может быть расширена до чего-либо, что не будет оцениваться с =.=
оператора присваивания. Вы можете утверждать, что мой скрипт не проверяет свои аргументы. Это правда. Я даже не проверяю, есть ли какой-либо аргумент или число аргументов является действительным. Но это было намеренно. ОП может добавить такие проверки, если он хочет.v
(лучше ее значение) в качестве второго аргумента функции assign. Таким образом, его значение должно быть справа от назначения. Необходимо процитировать аргумент функцииassign
. Я добавил эту тонкость в мою публикацию.С помощью нескольких приемов вы можете фактически передать именованные параметры в функции вместе с массивами (протестировано в bash 3 и 4).
Метод, который я разработал, позволяет получить доступ к параметрам, переданным в функцию, подобную этой:
Другими словами, вы можете не только вызывать параметры по их именам (что делает ядро более читабельным), но и передавать массивы (и ссылки на переменные - эта функция работает только в bash 4.3)! Кроме того, все отображаемые переменные находятся в локальной области, как и 1 доллар (и другие).
Код, который делает эту работу, довольно легкий и работает как в bash 3, так и в bash 4 (это единственные версии, с которыми я его тестировал). Если вас интересуют другие подобные хитрости, которые делают разработку с помощью bash намного приятнее и проще, вы можете взглянуть на мою среду Bash Infinity Framework , для которой был разработан приведенный ниже код.
источник
Это подходит?
источник
eval
подвержено произвольному выполнению команды.eval
линии более безопасными? Обычно, когда я думаю, что мне нужен eval, я решаю не использовать * sh и переключаться на другой язык. С другой стороны, используя это в scrips для добавления записей в некоторые переменные, подобные PATH, он будет работать со строковыми константами, а не с пользовательским вводом ...eval
безопасно - но это требует много мыслей. Если вы просто пытаетесь сослаться на параметр, вы захотите сделать что-то вроде этого:eval "$1=\"\$2\""
приeval's
первом проходе он оценивает только $ 1, а при втором - value = "$ 2". Но вам нужно сделать что-то еще - здесь это не нужно."${1##*[;"$IFS"]}=\"\$2\""
- и даже это идет без гарантии. Илиeval "$(set -- $1 ; shift $(($#-1)) ; echo $1)=\"\$2\""
. Это не легко.Именованные аргументы просто не соответствуют синтаксису Bash. Bash был разработан для итеративного улучшения оболочки Bourne. Как таковой, он должен гарантировать, что определенные вещи работают между двумя оболочками в максимально возможной степени. Таким образом, это не означает, что в целом сценарий проще, он просто лучше, чем Борн, и при этом гарантирует, что если вы перенесете сценарий из среды Борна в
bash
максимально простой режим . Это не тривиально, так как многие оболочки по-прежнему рассматривают Борн как стандарт де-факто. Поскольку люди пишут свои сценарии для Bourne-совместимости (для этой мобильности), потребность остается в силе и вряд ли когда-либо изменится.Возможно, вам лучше рассмотреть другой сценарий оболочки (например,
python
или что-то еще) полностью, если это вообще возможно. Если вы сталкиваетесь с ограничениями языка, вам нужно начать использовать новый язык.источник
bash
нашей жизни это было правдой. Но сейчас конкретные положения сделаны. Полные справочные переменные теперь доступны вbash 4.3
- см . Ответ Дероберта .Со стандартным
sh
синтаксисом (будет работать вbash
, а не только вbash
), вы можете сделать:Как и для решений, использующих
bash
«s»declare
, это безопасно, если$1
содержит допустимое имя переменной.источник
НА ИМЕННЫХ АРГАХ:
Это очень просто сделать и
bash
не нужно вообще - это базовое POSIX-поведение при назначении через расширение параметров:Для демонстрации в том же духе, что и в @Graeme, но в переносном виде:
И там я только делаю
str=
чтобы убедиться, что оно имеет нулевое значение, потому что расширение параметра имеет встроенную защиту от переназначения встроенной среды оболочки, если оно уже установлено.РЕШЕНИЕ:
Для вашей конкретной проблемы я не считаю именованные аргументы необходимыми, хотя они, безусловно, возможны. Используйте
$IFS
вместо:Вот что я получаю, когда запускаю его:
Заметьте, что это только добавило аргументы, которых еще не было
$PATH
или которые были раньше? Или даже, что потребовалось больше, чем один аргумент?$IFS
удобноисточник
assign
здесь. Если у вас есть вопросы о том, как это работает, я с удовольствием отвечу. И, кстати, если вы действительно хотите именованные аргументы, вы можете посмотреть на этот мой другой ответ, в котором я покажу, как объявить функцию, названную для аргументов другой функции: unix.stackexchange.com/a/120531/52934Я не могу найти ничего похожего на ruby, python и т. Д., Но мне это кажется ближе
На мой взгляд, читаемость лучше, 4 строки избыточны для объявления имен ваших параметров. Смотрится ближе к современным языкам.
источник
a=$1 b=$2 ...
работает так же хорошо.