Найкращий спосіб прочитати конфігураційний файл у bash


23

Який найкращий спосіб прочитати конфігураційний файл у bash?
Наприклад, у вас є сценарій, і ви не бажаєте заповнювати всі конфігурації вручну кожного разу, коли ви викликаєте сценарій.

Редагувати 1: Я думаю, що я цього не зрозумів, тому: те, що я хочу, це ... у мене є конфігураційний файл, який подібний

variable_name value  
variable_name value ...  

і я хочу це прочитати. Я знаю, що міг би просто похвастатись за аргументи, які я шукаю, або так ... але, можливо, є більш розумний спосіб :)


2
Вам доведеться показати, яку конфігурацію ви маєте на увазі. Наведіть приклад.
муру

Дивіться також дуже схоже запитання щодо Unix & Linux StackExchange.
Майкл

Відповіді:


38

Як сказав mbiber, sourceще один файл. Наприклад, ваш конфігураційний файл (скажімо some.config) буде:

var1=val1
var2=val2

І ваш сценарій може виглядати так:

#! /bin/bash

# Optionally, set default values
# var1="default value for var1"
# var1="default value for var2"

. /path/to/some.config

echo "$var1" "$var2"

Багато файлів /etc/defaultзазвичай служать файлами конфігурації для інших скриптів оболонки аналогічним чином. Дуже поширений приклад з публікацій тут /etc/default/grub. Цей файл використовується для встановлення параметрів конфігурації для GRUB, оскільки grub-mkconfigце сценарій оболонки, який його джерело:

sysconfdir="/etc"
#…
if test -f ${sysconfdir}/default/grub ; then
  . ${sysconfdir}/default/grub
fi

Якщо ви дійсно повинні обробити конфігурацію форми:

var1 some value 1
var2 some value 2

Тоді ви могли б зробити щось на кшталт:

while read var value
do
    export "$var"="$value"
done < /path/to/some.config

(Ви також можете зробити щось на кшталт eval "$var=$value", але це ризикованіше, ніж джерело скрипту. Ви можете ненароком зламати це простіше, ніж джерело, який ви отримаєте.)


Це чудовий спосіб, я міг би використовувати пробіл для заміни sed для "="
IcyIcyIce

1
@IcyIcyIce Просто не треба. Чому ви не можете написати це з =самого початку?
muru

1
@IcyIcyIce Саме так має бути. Код оболонки ви можете використовувати в різних файлах /etc/default- і в основному для хорошого використання. Якщо ваш неосвічений користувач має доступ до конфігурації для чогось, що працює як root, це вже втрачена причина.
муру

1
@IcyIcyIce змусити своїх вчителів уточнити, чого вони хочуть. Частина навчання розробці програмного забезпечення - це чітке ознайомлення з вимогами.
муру

1
@IcyIcyIce див. Оновлення.
муру

4

Очевидно, я bashтут не фахівець, але концепція не повинна відрізнятися будь-якою мовою:

Приклад

У наведеному нижче прикладі ви можете використовувати (дуже) базовий скрипт або для встановлення рядка, або для друку рядка, як встановлено у вашому конфігураційному файлі:

#!/bin/bash

# argument to set a new string or print the set string
arg=$1
# possible string as second argument
string=$2
# path to your config file
configfile="$HOME/stringfile"

# if the argument is: "set", write the string (second argument) to a file
if [ "$arg" == "set" ]
then
echo "$string" > $configfile 
# if the argunment is "print": print out the set string, as defined in your file
elif [ "$arg" == "print" ]
then 
echo "$( cat $configfile )"
fi

Потім

  • Щоб встановити рядок у ваш конфігураційний файл:

    $ '/home/jacob/Bureaublad/test.sh' set "Een aap op een fiets, hoe vind je zoiets?"
  • Згодом для друку рядка, як визначено у вашому "configfile":

    $ '/home/jacob/Bureaublad/test.sh' print
    Een aap op een fiets, hoe vind je zoiets?

Звичайно, у реальному застосованому сценарії потрібно додати багато речей, щоб переконатися, що аргументи правильні, вирішити, що робити, коли введення невірно, файл налаштувань не існує тощо, але:

Це основна ідея


дякую, я просто оновлюю питання, я думаю, що я не давав зрозуміти це ... але у простих випадках це спрацювало б як шарм ofc
IcyIcyIce

4

Використовуйте sourceабо .для завантаження у файл.

source /path/to/file

або

. /path/to/file

Також рекомендується перевірити, чи існує файл, перш ніж завантажувати його, оскільки ви не хочете продовжувати запускати сценарій, якщо файл конфігурації відсутній.


0

Я використовую цей ...

#!/bin/bash

CFG_FILE=/etc/test.conf
CFG_CONTENT=$(cat $CFG_FILE | sed -r '/[^=]+=[^=]+/!d' | sed -r 's/\s+=\s/=/g')
eval "$CFG_CONTENT"

Конфігураційний файл розбирається з sed і потім оцінюється як прості призначення змінної

Перші значення ключового синтаксичного аналізу (підтримує також = оточений пробілами)

Другий sed видаляє пробіли навколо = знак для дійсного призначення змінної

Подальше лікування седом може бути додано

Буде видалено весь невідповідний текст у конф-файлі (включаючи # або; коментар та інше)

Майте на увазі, що однорядкові команди оболонки також можна оцінити з цього конфігураційного файлу!


1
Марне використанняcat . Чому ви sedдвічі посилаєтесь назад? Ви можете ланцюжок sedкоманд так:sed -r '/[^=]+=[^=]+/!d;s/\s+=\s/=/g'
Девід Фоерстер

Також ця sedкоманда генерує порожній вихід для записів зразкового конфігураційного файла у запитанні. -1
Девід Фоерстер

1
Ще одне можливе вдосконалення: використовуйте .команду та процес переадресацію замість тимчасових змінних, щоб утримувати вихід підпроцесу:. <(sed ... "$CFG_FILE")
Девід Фоерстер,

Звичайно, мій приклад використовує ключ = значення, як конфігураційний файл. Це краща практика, ніж "ключова цінність". Використовуючи ключ = значення, працює мій приклад. Признаю, ваше ланцюг команд sed краще, але команда-джерело очікує файл, щоб ми могли використовувати:, eval $(sed -r '/[^=]+=[^=]+/!d;s/\s+=\s/=/g' "$CFG_FILE")що краще зрозуміти, що відбувається.
smARTin

Так, .очікується , що заміна файлу та процесу буде розширена на файл. . <(echo echo foo)працює так, як очікувалося в Bash v4.3.11. У малих прикладах це, мабуть, не має значення. Я б краще не передавав кілька кілобайт через заміну команди.
Девід Фоерстер

0
#------------------------------------------------------------------------------
# parse the ini like $0.$host_name.cnf and set the variables
# cleans the unneeded during after run-time stuff. Note the MainSection
# courtesy of : http://mark.aufflick.com/blog/2007/11/08/parsing-ini-files-with-sed
#------------------------------------------------------------------------------
doParseConfFile(){
    # set a default cnfiguration file
    cnf_file="$run_unit_bash_dir/$run_unit.cnf"

    # however if there is a host dependant cnf file override it
    test -f "$run_unit_bash_dir/$run_unit.$host_name.cnf" \
    && cnf_file="$run_unit_bash_dir/$run_unit.$host_name.cnf"

    # yet finally override if passed as argument to this function
    # if the the ini file is not passed define the default host independant ini file
    test -z "$1" || cnf_file=$1;shift 1;


    test -z "$2" || ini_section=$2;shift 1;
    doLog "DEBUG read configuration file : $cnf_file"
    doLog "INFO read [$ini_section] section from config file"

    # debug echo "@doParseConfFile cnf_file:: $cnf_file"
    # coud be later on parametrized ...
    test -z "$ini_section" && ini_section='MAIN_SETTINGS'

    doLog "DEBUG reading: the following configuration file"
    doLog "DEBUG ""$cnf_file"
    ( set -o posix ; set ) | sort >"$tmp_dir/vars.before"

    eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
        -e 's/#.*$//' \
        -e 's/[[:space:]]*$//' \
        -e 's/^[[:space:]]*//' \
        -e "s/^\(.*\)=\([^\"']*\)$/\1=\"\2\"/" \
        < $cnf_file \
        | sed -n -e "/^\[$ini_section\]/,/^\s*\[/{/^[^#].*\=.*/p;}"`

    ( set -o posix ; set ) | sort >"$tmp_dir/vars.after"

    doLog "INFO added the following vars from section: [$ini_section]"
    cmd="$(comm -3 $tmp_dir/vars.before $tmp_dir/vars.after | perl -ne 's#\s+##g;print "\n $_ "' )"
    echo -e "$cmd"
    echo -e "$cmd" >> $log_file
    echo -e "\n\n"
    sleep 1; printf "\033[2J";printf "\033[0;0H" # and clear the screen
}
#eof func doParseConfFile
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.