बैश में कॉन्फिग फाइल पढ़ने का सबसे अच्छा तरीका


23

बैश में कॉन्फिग फाइल पढ़ने का सबसे अच्छा तरीका क्या है?
उदाहरण के लिए, आपके पास एक स्क्रिप्ट है और स्क्रिप्ट को कॉल करने पर हर बार मैन्युअल रूप से सभी कॉन्फ़िगरेशन को भरने के लिए तैयार नहीं हैं।

संपादित करें 1: मुझे लगता है कि मैंने इसे स्पष्ट नहीं किया, इसलिए: मुझे जो चाहिए वह है ... मेरे पास एक configfile है जो पसंद है

variable_name value  
variable_name value ...  

और मुझे वह पढ़ना है। मुझे पता है कि मैं इसे उन तर्कों के लिए टाल सकता हूं, जिन्हें मैं ढूंढ रहा हूं ... या शायद ... लेकिन अधिक बुद्धिमान तरीका है :)


2
आपको यह दिखाना होगा कि आप किस प्रकार के विन्यास का मतलब है। एक उदाहरण दें।
मुरु

यूनिक्स और लिनक्स 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 स्थानापन्न
व्हाट्सएप का

1
@IcyIcyIce बस नहीं है। आप इसे =शुरू से क्यों नहीं लिख सकते ?
मुरु

1
@IcyIcyIce यही है कि यह कैसे माना जाता है। आप विभिन्न फ़ाइलों में शेल कोड का उपयोग कर सकते हैं /etc/default- और ज्यादातर अच्छे उपयोग के लिए। यदि आपके क्लूलेस उपयोगकर्ता के पास रूट के रूप में चलने वाली किसी चीज़ के लिए कॉन्फ़िगरेशन तक पहुंच है, तो यह पहले से ही एक खो कारण है।
मुरु

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?"
  • इसके बाद, स्ट्रिंग को प्रिंट करने के लिए, जैसा कि आपके "कॉन्फिगराइल" में परिभाषित किया गया है:

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

बेशक, एक वास्तविक लागू स्क्रिप्ट में, आपको यह सुनिश्चित करने के लिए बहुत सारे सामान जोड़ने की ज़रूरत है कि तर्क सही हैं, यह तय करें कि इनपुट गलत होने पर क्या करना है, सेटिंग्स फ़ाइल मौजूद नहीं है, लेकिन:

यह मूल विचार है


धन्यवाद, मैं सिर्फ इस सवाल को अपडेट कर रहा हूं मुझे लगता है कि मैंने इसे स्पष्ट नहीं किया है ... लेकिन साधारण मामलों में यह एक आकर्षण की तरह काम करेगा
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"

Conf फ़ाइल को sed के साथ पार्स किया गया है और फिर सरल चर asignments के रूप में मूल्यांकन किया गया है

पहली सीड पार्सिंग प्रमुख मान (समर्थन भी = रिक्त स्थान से घिरा हुआ)

दूसरा 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)बाश v4.3.11 में उम्मीद के मुताबिक काम करता है। छोटे उदाहरणों में यह शायद मायने नहीं रखेगा। मैं हालांकि कमांड प्रतिस्थापन के माध्यम से कई किलोबाइट पास नहीं करूंगा।
डेविड फ़ॉस्टर 15

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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.