Прочитайте конфигурационный файл в BASH без использования "source"
Я пытаюсь прочитать конфигурационный файл, который отформатирован следующим образом:
USER = username
TARGET = arrows
Я понимаю, что если бы я избавился от пробелов, я мог бы просто загрузить файл конфигурации, но по соображениям безопасности я пытаюсь избежать этого. Я знаю, что есть способ прочитать файл конфигурации по строкам. Я думаю, что процесс выглядит примерно так:
- Чтение строк в массив
- Отфильтровать все строки, начинающиеся С#
- искать имена переменных в массиве
После этого я потерялся. Любая помощь будет очень признательна. Я пробовал что-то вроде этого без успеха:
backup2.config>cat ~/1
grep '^[^#].*' | while read one two;do
echo $two
done
Я вытащил это из сообщения в форуме, которое я нашел, просто не знаю, как изменить его, чтобы он соответствовал моим потребностям, поскольку я так новичок в сценариях оболочки.
http://www.linuxquestions.org/info/programming-9/bash-shell-program-read-a-configuration-file-276852/
Можно ли автоматически назначать переменную путем циклического перемещения по обеим массивам?
for (( i = 0 ; i < ${#VALUE[@]} ; i++ ))
do
"${NAME[i]}"=VALUE[i]
done
echo $USER
Таким образом, чтобы вызов $USER выдавал "имя пользователя"? Вышеприведенный код не работает, но я знаю, что решение похоже на это.
Ответы
Ответ 1
Следующий script выполняет итерацию по каждой строке входного файла (vars в моем случае) и соответствует шаблону с =
. Если знак равенства найден, он будет использовать Расширение параметров, чтобы проанализировать имя переменной из значения. Затем он сохраняет каждую часть в собственном массиве, имени и значении, соответственно.
#!/bin/bash
i=0
while read line; do
if [[ "$line" =~ ^[^#]*= ]]; then
name[i]=${line%% =*}
value[i]=${line#*= }
((i++))
fi
done < vars
echo "total array elements: ${#name[@]}"
echo "name[0]: ${name[0]}"
echo "value[0]: ${value[0]}"
echo "name[1]: ${name[1]}"
echo "value[1]: ${value[1]}"
echo "name array: ${name[@]}"
echo "value array: ${value[@]}"
Ввод
$ cat vars
sdf
USER = username
TARGET = arrows
asdf
as23
Выход
$ ./varscript
total array elements: 2
name[0]: USER
value[0]: username
name[1]: TARGET
value[1]: arrows
name array: USER TARGET
value array: username arrows
Ответ 2
Во-первых, USER
- это переменная среды оболочки, поэтому было бы лучше, если бы вы использовали что-то еще. Использование строчных или смешанных имен переменных случая - это способ избежать столкновений имен.
#!/bin/bash
configfile="/path/to/file"
shopt -s extglob
while IFS='= ' read lhs rhs
do
if [[ $lhs != *( )#* ]]
then
# you can test for variables to accept or other conditions here
declare $lhs=$rhs
fi
done < "$configfile"
Это устанавливает в файле vars значение, связанное с ним.
echo "Username: $USER, Target: $TARGET"
выводит
Username: username, Target: arrows
Ответ 3
У меня есть script, который принимает только очень ограниченное количество настроек и обрабатывает их по одному, поэтому я адаптировал SiegeX-ответ на белый список настроек, которые меня волнуют и действуют на них, когда дело доходит до них.
Я также удалил требование для пробелов вокруг =
в пользу игнорирования любых существующих с помощью функции trim
из другого ответа.
function trim()
{
local var=$1;
var="${var#"${var%%[![:space:]]*}"}"; # remove leading whitespace characters
var="${var%"${var##*[![:space:]]}"}"; # remove trailing whitespace characters
echo -n "$var";
}
while read line; do
if [[ "$line" =~ ^[^#]*= ]]; then
setting_name=$(trim "${line%%=*}");
setting_value=$(trim "${line#*=}");
case "$setting_name" in
max_foos)
prune_foos $setting_value;
;;
max_bars)
prune_bars $setting_value;
;;
*)
echo "Unrecognised setting: $setting_name";
;;
esac;
fi
done <"$config_file";
Ответ 4
Спасибо SiegeX. Я думаю, что более поздние обновления, о которых вы упомянули, не отражены в этом URL-адресе.
Мне пришлось отредактировать регулярное выражение, чтобы удалить кавычки, чтобы заставить его работать. С кавычками возвращаемый массив пуст.
i=0
while read line; do
if [[ "$line" =~ ^[^#]*= ]]; then
name[i]=${line%% =*}
value[i]=${line##*= }
((i++))
fi
done < vars
Еще лучшая версия.
i=0
while read line; do
if [[ "$line" =~ ^[^#]*= ]]; then
name[i]=`echo $line | cut -d'=' -f 1`
value[i]=`echo $line | cut -d'=' -f 2`
((i++))
fi
done < vars
У первой версии есть проблемы, если в файле конфигурации нет места до и после "=". Также, если значение отсутствует, я вижу, что имя и значение заполняются одинаковыми. Во второй версии нет ни одного из них. Кроме того, он обрезает нежелательные начальные и конечные пробелы.
Эта версия считывает значения, которые могут иметь = внутри нее. Более ранняя версия распадается при первом возникновении =.
i=0
while read line; do
if [[ "$line" =~ ^[^#]*= ]]; then
name[i]=`echo $line | cut -d'=' -f 1`
value[i]=`echo $line | cut -d'=' -f 2-`
((i++))
fi
done < vars