Удобно, когда скрипт берет настройки из некоего файла. Например, можно дать доступ к настройкам пользователю, не давая ему изменять собственно скрипт. Чтобы не повторять довольно длинный кусок кода в каждом скрипте каждый раз, когда надо получить какую-то настройку, лучше написать функцию, которая будет лезть в файл настроек и брать оттуда нужную переменную.
Тут вылезает другая грабля: функции в bash не умеют возвращать свои результаты. Максимум, на что они способны - вернуть код завершения. А как быть со строками?
На основании http://www.linuxjournal.com/content/return-values-bash-functions я нарисовал функцию getVar, которая хранится в отдельном файле и подключается в скриптах как source.
Эта функция читает определенный конфиг (задается в теле source-a), ищет в нем пару "переменная=значение" и возвращает "значение". Как возвращает? А просто пишет его на стандартный вывод, для перехвата которого используем $()
Просто, ясно и никакой мистики. Может быть не так удобно, как было бы
но уж чем богаты, тому и рады.
До недавнего времени всё работало, но вот я решил поправить конфиг и добавил в него что-то вроде:
Разумеется, такой вариант не прокатил, потому что это файл настроек, а не исполняемый файл, и вместо подстановки значения из ПОВВЭК, моя Переменная получала значение "$ПОВВЭК", что, по понятным причинам, меня не радовало.
Ладно, разобрался, закомментировал неправильное, написал как положено:
Запускаю сценарий, использующий Переменную, и выпадаю в осадок: она всё равно получает значение "$ПОВВЭК", которое закомментировано! Что за чертовщина? Чертовщина крылась в том, что я grep-ом искал первое появление имени Переменной в конфиге, и как-то не учел, что первым вполне может оказаться закомментированное появление.
Изначально выглядело это так:
Тихо ищем переменную в файле конфигурации до первого совпадения. Если grep вернул ошибку, то мы тоже сигналим об этом кодом завершения 2 (код 1 зарезервирован для случая, если по запарке функцию вызвали без параметров) и не возвращаем никакого значения. (возможно, потом сделаю слегка расширенный вариант функции, который будет принимать не обязательный второй параметр - значение по умолчанию, которое будет возвращаться, если переменной нет в конфиге).
В исправленном варианте пришлось делать конвейер подлиннее:
Сначала пропускаем все строки, которые либо пустые, либо начинаются с диеза, перед которым может идти что-нибудь пробельное. В отобранном "материале" ищем довольно строго: искомое имя должно находиться в начале строки, и сразу после него должен быть знак равенства. Между именем и знаком может быть некоторое количество пробелов и/или табуляций для эстетов, выравнивающих столбцы в своих конфигах.
Поскольку Значение вполне может начинаться с пробела, то проверку на пробел справа от знака равенства я не делаю умышленно: всё, что идет справа от знака, возвращается как результат работы функции "as is".
Возможно, удастся обе предыдущие проверки спихнуть на awk, но сейчас мне лень, да и некогда этим заниматься. Желающие совершить сей подвиг могут отписаться в комментах.
Итак, окончательный текст файла source:
Тут вылезает другая грабля: функции в bash не умеют возвращать свои результаты. Максимум, на что они способны - вернуть код завершения. А как быть со строками?
На основании http://www.linuxjournal.com/content/return-values-bash-functions я нарисовал функцию getVar, которая хранится в отдельном файле и подключается в скриптах как source.
Эта функция читает определенный конфиг (задается в теле source-a), ищет в нем пару "переменная=значение" и возвращает "значение". Как возвращает? А просто пишет его на стандартный вывод, для перехвата которого используем $()
Переменная=$(getVar ИскомоеИмяПеременной)
Просто, ясно и никакой мистики. Может быть не так удобно, как было бы
Переменная=getVar(ИскомоеИмяПеременной)
но уж чем богаты, тому и рады.
До недавнего времени всё работало, но вот я решил поправить конфиг и добавил в него что-то вроде:
Переменная=$ПеременнаяОписаннаяВышеВЭтомКонфиге
Разумеется, такой вариант не прокатил, потому что это файл настроек, а не исполняемый файл, и вместо подстановки значения из ПОВВЭК, моя Переменная получала значение "$ПОВВЭК", что, по понятным причинам, меня не радовало.
Ладно, разобрался, закомментировал неправильное, написал как положено:
# Так нельзя: Переменная=$ПеременнаяОписаннаяВышеВЭтомКонфиге
Переменная=ЗначениеТакоеЖеКакУДругойПеременной
Запускаю сценарий, использующий Переменную, и выпадаю в осадок: она всё равно получает значение "$ПОВВЭК", которое закомментировано! Что за чертовщина? Чертовщина крылась в том, что я grep-ом искал первое появление имени Переменной в конфиге, и как-то не учел, что первым вполне может оказаться закомментированное появление.
Изначально выглядело это так:
grep -m 1 $1 $sourceConfig -q; if [ "$?" -ne "0" ]; then return 2; fi
Тихо ищем переменную в файле конфигурации до первого совпадения. Если grep вернул ошибку, то мы тоже сигналим об этом кодом завершения 2 (код 1 зарезервирован для случая, если по запарке функцию вызвали без параметров) и не возвращаем никакого значения. (возможно, потом сделаю слегка расширенный вариант функции, который будет принимать не обязательный второй параметр - значение по умолчанию, которое будет возвращаться, если переменной нет в конфиге).
В исправленном варианте пришлось делать конвейер подлиннее:
grep -vE '^[[:space:]]*#|^[[:space:]]*$' $sourceConfig|grep -m 1 -E "^$1[[:space:]]*\=" -q; if [ "$?"...
Сначала пропускаем все строки, которые либо пустые, либо начинаются с диеза, перед которым может идти что-нибудь пробельное. В отобранном "материале" ищем довольно строго: искомое имя должно находиться в начале строки, и сразу после него должен быть знак равенства. Между именем и знаком может быть некоторое количество пробелов и/или табуляций для эстетов, выравнивающих столбцы в своих конфигах.
Поскольку Значение вполне может начинаться с пробела, то проверку на пробел справа от знака равенства я не делаю умышленно: всё, что идет справа от знака, возвращается как результат работы функции "as is".
Возможно, удастся обе предыдущие проверки спихнуть на awk, но сейчас мне лень, да и некогда этим заниматься. Желающие совершить сей подвиг могут отписаться в комментах.
Итак, окончательный текст файла source:
# Из этого файла берем нужное значение, если есть
sourceConfig=/путь/к/файлу/настроек
getVar ()
# http://www.linuxjournal.com/content/return-values-bash-functions
{
# если забыли передать параметр, выходим с кодом 1
if [ -z $1 ]; then return 1; fi
# если такой переменной нет, выходим с кодом 2
grep -vE '^[[:space:]]*#|^[[:space:]]*$' $sourceConfig|grep -m 1 -E "^$1[[:space:]]*\=" -q; if [ "$?" -ne "0" ]; then return 2; fi
# значения в конфиге должны храниться в формате "переменная=значение", поэтому устанавливаем для awk разделитель полей "=" и выводим на stdout второе поле строки.
grep -vE '^[[:space:]]*#|^[[:space:]]*$' $sourceConfig|grep -m 1 -E "^$1[[:space:]]*\="|awk -F \= -e '{print $2}'
return 0
}
Комментариев нет:
Отправить комментарий
Пожалуйста, воздержитесь от грубостей и персональных нападок.
Я не против матерщины, но она должна быть уместной и использоваться для выражения эмоций, а не в качестве основного средства выражения мыслей.