मैं शेल स्क्रिप्ट के भीतर INI मान कैसे प्राप्त कर सकता हूं?


97

मेरे पास एक पैरामीटर है। मैं फ़ाइल, जैसे:

[parameters.ini]
    database_user    = user
    database_version = 20110611142248

मैं एक bash शेल स्क्रिप्ट के भीतर से पैरामीटर.ini फ़ाइल में निर्दिष्ट डेटाबेस संस्करण को पढ़ना और उसका उपयोग करना चाहता हूं ताकि मैं इसे संसाधित कर सकूं।

#!/bin/sh    
# Need to get database version from parameters.ini file to use in script    
php app/console doctrine:migrations:migrate $DATABASE_VERSION

यह मैं कैसे करूंगा?


2
क्या इनमें से कोई भी उत्तर सभी वर्गों का सम्मान करता है?
मैनुएल श्नाइड

जवाबों:


83

कैसे उस लाइन के लिए grepping तो awk का उपयोग कर के बारे में

version=$(awk -F "=" '/database_version/ {print $2}' parameters.ini)

6
इसमें '=' ​​के बाद रिक्त स्थान शामिल होंगे।

10
रिक्त स्थान को ट्रिम करने के लिए, | tr -d ' 'अंत में जोड़ें ।
kenorb

22
यह वास्तव में एक अच्छा समाधान नहीं है। प्रत्येक 'डेटाबेस_वेशन' वेरिएबल वाले 2 [पैरामीटर्स.इन] सेक्शन के बारे में सोचें। आपको मूल्य दो बार मिलता है।
nerdoc

4
हाँ क्रुदिनी की तरह एक विशेष आई पार्सर पर विचार करें, क्योंकि ऊपर द्वारा संभाले नहीं गए कई किनारे के मामले हैं
पिक्सेलबीट

3
अभी भी उपयोगी और मूल ini फ़ाइलों के लिए तेज।
सिरिल एन।

51

आप ini मानों की व्याख्या करने के लिए bash देशी पार्सर का उपयोग कर सकते हैं:

$ source <(grep = file.ini)

नमूना फ़ाइल:

[section-a]
  var1=value1
  var2=value2
  IPS=( "1.2.3.4" "1.2.3.5" )

चर का उपयोग करने के लिए, आप बस उन्हें प्रिंट कर रहे हैं echo $var1:। जैसा कि ऊपर दिखाया गया है ( echo ${IPS[@]}) भी आप सरणियों का उपयोग कर सकते हैं ।

यदि आप केवल इसके लिए केवल एक मूल्य चाहते हैं:

source <(grep var1 file.ini)

डेमो के लिए, इस रिकॉर्डिंग को एसिंसीमा पर देखें

यह आसान है क्योंकि आपको डेटा को पार्स करने के लिए किसी बाहरी पुस्तकालय की आवश्यकता नहीं है, लेकिन यह कुछ नुकसान के साथ आता है। उदाहरण के लिए:

  • यदि आपके पास =(चर नाम और मान) के बीच रिक्त स्थान हैं , तो आप पहले रिक्त स्थान को ट्रिम कर सकते हैं, जैसे

      $ source <(grep = file.ini | sed 's/ *= */=/g')

    या यदि आप रिक्त स्थान (मध्य में) का उपयोग नहीं करते हैं, तो उपयोग करें:

      $ source <(grep = file.ini | tr -d ' ')
  • ;टिप्पणियों का समर्थन करने के लिए, उन्हें प्रतिस्थापित करें #:

      $ sed "s/;/#/g" foo.ini | source /dev/stdin
  • अनुभाग समर्थित नहीं हैं (उदाहरण के लिए यदि आप हैं [section-name], तो आप इसे फ़िल्टर कर सकते हैं जैसा कि ऊपर दिखाया गया है, उदाgrep = ), अन्य अनपेक्षित त्रुटियों के लिए भी।

    आप विशिष्ट अनुभाग, उपयोग के तहत विशिष्ट मूल्य को पढ़ने के लिए की जरूरत है grep -A, sed, awkयाex )।

    उदाहरण के लिए

      source <(grep = <(grep -A5 '\[section-b\]' file.ini))

    नोट: -A5अनुभाग में पढ़ने के लिए पंक्तियों की संख्या कहाँ है। डिबग के sourceसाथ बदलें cat

  • यदि आपको कोई पार्सिंग त्रुटि मिली है, तो उन्हें जोड़कर अनदेखा करें: 2>/dev/null

यह सभी देखें:


1
लेकिन ... source <(grep = <(grep -A5 '\[section-b\]' file.ini))यह इसके लिए काम नहीं करेगा: [sec a] 1 a = 1 b = 2 c = 3 [sec b] a = 2 b = 3 [sec c] a = 0। जहां लाइनों के साथ कोई निश्चित नियम नहीं है
मनोजोइक

मैं स्रोत का उपयोग करने की कोशिश की, लेकिन जब मैं $ var1 गूंज यह कुछ भी नहीं देता है। क्यों?
ए। घोष

@ A. मुझे यकीन नहीं है, मेरे लिए काम करता है। सुनिश्चित करें कि आप बैश शेल का उपयोग कर रहे हैं। देखें: asciinema.org/a/306481
kenorb

यह सुरुचिपूर्ण होता, लेकिन ओएस एक्स (कैटालिना) में काम करने में असफल रहा। यह कमांड प्रॉम्प्ट से zsh (करंट डिफॉल्ट शेल) में काम करता है, लेकिन एक बार इसे स्क्रिप्ट में डालने के बाद, मुझे त्रुटि मिलती है syntax error near unexpected token '('। बैश के साथ, यह चुपचाप संकेत और स्क्रिप्ट दोनों से विफल रहता है।
MiRIN

29

बैश इन फ़ाइलों के लिए एक पार्सर प्रदान नहीं करता है। स्पष्ट रूप से आप एक awk कमांड या एक-दो कॉल का उपयोग कर सकते हैं, लेकिन यदि आप bash-priest हैं और किसी अन्य शेल का उपयोग नहीं करना चाहते हैं, तो आप निम्नलिखित अस्पष्ट कोड आज़मा सकते हैं:

#!/usr/bin/env bash
cfg_parser ()
{
    ini="$(<$1)"                # read the file
    ini="${ini//[/\[}"          # escape [
    ini="${ini//]/\]}"          # escape ]
    IFS=$'\n' && ini=( ${ini} ) # convert to line-array
    ini=( ${ini[*]//;*/} )      # remove comments with ;
    ini=( ${ini[*]/\    =/=} )  # remove tabs before =
    ini=( ${ini[*]/=\   /=} )   # remove tabs after =
    ini=( ${ini[*]/\ =\ /=} )   # remove anything with a space around =
    ini=( ${ini[*]/#\\[/\}$'\n'cfg.section.} ) # set section prefix
    ini=( ${ini[*]/%\\]/ \(} )    # convert text2function (1)
    ini=( ${ini[*]/=/=\( } )    # convert item to array
    ini=( ${ini[*]/%/ \)} )     # close array parenthesis
    ini=( ${ini[*]/%\\ \)/ \\} ) # the multiline trick
    ini=( ${ini[*]/%\( \)/\(\) \{} ) # convert text2function (2)
    ini=( ${ini[*]/%\} \)/\}} ) # remove extra parenthesis
    ini[0]="" # remove first element
    ini[${#ini[*]} + 1]='}'    # add the last brace
    eval "$(echo "${ini[*]}")" # eval the result
}

cfg_writer ()
{
    IFS=' '$'\n'
    fun="$(declare -F)"
    fun="${fun//declare -f/}"
    for f in $fun; do
        [ "${f#cfg.section}" == "${f}" ] && continue
        item="$(declare -f ${f})"
        item="${item##*\{}"
        item="${item%\}}"
        item="${item//=*;/}"
        vars="${item//=*/}"
        eval $f
        echo "[${f#cfg.section.}]"
        for var in $vars; do
            echo $var=\"${!var}\"
        done
    done
}

उपयोग:

# parse the config file called 'myfile.ini', with the following
# contents::
#   [sec2]
#   var2='something'
cfg.parser 'myfile.ini'

# enable section called 'sec2' (in the file [sec2]) for reading
cfg.section.sec2

# read the content of the variable called 'var2' (in the file
# var2=XXX). If your var2 is an array, then you can use
# ${var[index]}
echo "$var2"

बैश इनि-पार्सर द ओल्ड स्कूल देवओप्स ब्लॉग साइट पर पाया जा सकता है ।


3
हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक हिस्सों को यहां शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं।
एलेक्सी

8
मैं आम तौर पर इस तरह की टिप्पणियां देने वाला व्यक्ति हूं; मैं केवल इतना ही कह सकता हूं कि मैं युवा और बेवकूफ था :-)
फ्रेड्रिक पीहल

1
यदि आप इस स्निपेट को पसंद करते हैं, तो github.com/albfan/bash-ini-parser
albfan

3
सही ढंग से काम करने के लिए, cfg.parser के बजाय cfg_parser का उपयोग करने की आवश्यकता है
Wes

1
TYPO: "cfg.parser" को "cfg_parser" होना चाहिए।
Setop

26

सैड वन-लाइनर, जो वर्गों को ध्यान में रखता है। उदाहरण फ़ाइल:

[section1]
param1=123
param2=345
param3=678

[section2]
param1=abc
param2=def
param3=ghi

[section3]
param1=000
param2=111
param3=222

आप अनुभाग 2 से परम 2 चाहते हैं। निम्नलिखित चलाएँ:

sed -nr "/^\[section2\]/ { :l /^param2[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" ./file.ini

तुम्हे दूंगा

def

3
sed -nr "/ ^ \ [SECTION2 \] / {: l /^\s* [^##ades_*/ p; n; / ^ \ [/ q; bl;}" file.conf # को पूरा खंड प्राप्त करने के लिए; [SECTION2] और # हैश-शैली टिप्पणी लाइनों के साथ .conf शैली फ़ाइल के लिए टिप्पणियों के बिना। यदि आप सिर्फ एक पैरामीटर चाहते हैं तो paramname के लिए grep।
गौइथे

अगली पंक्तियों को पढ़ने की तुलना में बेहतर श्रेणीबद्ध पते का उपयोग करें:"/^\[section2\]/,/^\[/{...}"
बेसिन

1
अगर एक पर MAC: brew install gnu-sedऔर फिर gsed(अन्यथा sed: illegal option -- r) का उपयोग करें
19 frnhr

क्या कोई यह बता सकता है कि sed -nr "/^\[SECTION2\]/ { :l /^\s*[^#].*/ p; n; /^\[/ q; b l; }" अभिव्यक्ति कैसे काम करती है? धन्यवाद
foo_l

22

बस अपनी .ini फ़ाइल को बैश बॉडी में शामिल करें:

फ़ाइल example.ini :

DBNAME=test
DBUSER=scott
DBPASSWORD=tiger

फ़ाइल उदाहरण.श

#!/bin/bash
#Including .ini file
. example.ini
#Test
echo "${DBNAME}   ${DBUSER}  ${DBPASSWORD}"

2
यह चयनित उत्तर होना चाहिए। यह file.properties के साथ काम करता है और गलती सहिष्णु है (अंदर खाली लाइन के साथ फ़ाइल)। धन्यवाद
एंथनी

17
INI फ़ाइलों के [खंड] भाग को नहीं संभालता है।
Setop

यह सबसे अच्छा जवाब है!
JavaSheriff

17
उम्मीद है कि कोई भी कभी भी ini फ़ाइल में "rm -rf /" नहीं जोड़ता :(
HeyMan

1
सब-शेल में बहुत सुरक्षित: $ (? Example.ini; echo $ DBNAME)
रिच रेमर

14

मैंने अब तक जितने भी समाधान देखे हैं, उन सभी पर भी टिप्पणी की गई है। यह एक नहीं है, अगर टिप्पणी कोड है ;:

awk -F '=' '{if (! ($0 ~ /^;/) && $0 ~ /database_version/) print $2}' file.ini

2
यह स्वीकार किया जाना चाहिए उत्तर क्योंकि a) यह हैंडल से बाहर की रेखाओं को ब) सरल
बनाता है

1
यह भयानक है, ty @ पेंगुइन! उपयोग: 1. पूर्ण-पंक्ति टिप्पणियाँ अर्धविराम उपसर्ग के साथ अनुमत हैं (पंक्ति टिप्पणियों की कोई इनलाइन समाप्ति की अनुमति नहीं है); 2. व्हाट्सएप को परिणाम से दूर नहीं किया गया है (इसलिए यदि आईएनआई फ़ाइल में 'ए = 1' है, तो 'ए' के ​​लिए स्क्रिप्ट की खोज '1' का मूल्यांकन करती है)।
ऐनीएजाइल

1
रिक्त स्थान को ट्रिम करने के लिए, | tr -d ' 'अंत में जोड़ें ।
kenorb

इसमें सुझाए गए उत्तर के समान समस्या है; यह "database_version" के हर उदाहरण को
खोजता है

12

अधिक संभव समाधानों में से एक

dbver=$(sed -n 's/.*database_version *= *\([^ ]*.*\)/\1/p' < parameters.ini)
echo $dbver

8

In_- शैली my_file में my_key का मान प्रदर्शित करें :

sed -n -e 's/^\s*my_key\s*=\s*//p' my_file
  • -n - डिफ़ॉल्ट रूप से कुछ भी प्रिंट न करें
  • -e - अभिव्यक्ति निष्पादित करें
  • s/PATTERN//p - इस पैटर्न के बाद कुछ भी प्रदर्शित करें पैटर्न में:
  • ^ - पैटर्न लाइन की शुरुआत में शुरू होता है
  • \s - व्हाट्सएप चरित्र
  • * - शून्य या कई (व्हाट्सएप पात्र)

उदाहरण:

$ cat my_file
# Example INI file
something   = foo
my_key      = bar
not_my_key  = baz
my_key_2    = bing

$ sed -n -e 's/^\s*my_key\s*=\s*//p' my_file
bar

इसलिए:

एक पैटर्न खोजें जहां रेखा शून्य या कई व्हाट्सएप वर्णों के साथ शुरू होती है, उसके बाद स्ट्रिंग my_key , उसके बाद शून्य या कई व्हाट्सएप वर्ण, एक समान चिह्न, फिर शून्य या कई व्हाट्सएप वर्ण फिर से आते हैं। उस पैटर्न के बाद उस लाइन के बाकी कंटेंट को प्रदर्शित करें।


आपका उदाहरण काम नहीं करता ( barमुद्रित नहीं है), कम से कम यूनिक्स / ओएसएक्स पर।
kenorb

7

sed

आप sedini कॉन्फ़िगरेशन फ़ाइल को पार्स करने के लिए उपयोग कर सकते हैं , खासकर जब आप अनुभाग नाम जैसे:

# last modified 1 April 2001 by John Doe
[owner]
name=John Doe
organization=Acme Widgets Inc.

[database]
# use IP address in case network name resolution is not working
server=192.0.2.62
port=143
file=payroll.dat

इसलिए आप sedडेटा से ऊपर पार्स करने के लिए निम्न स्क्रिप्ट का उपयोग कर सकते हैं :

# Configuration bindings found outside any section are given to
# to the default section.
1 {
  x
  s/^/default/
  x
}

# Lines starting with a #-character are comments.
/#/n

# Sections are unpacked and stored in the hold space.
/\[/ {
  s/\[\(.*\)\]/\1/
  x
  b
}

# Bindings are unpacked and decorated with the section
# they belong to, before being printed.
/=/ {
  s/^[[:space:]]*//
  s/[[:space:]]*=[[:space:]]*/|/
  G
  s/\(.*\)\n\(.*\)/\2|\1/
  p
}

यह ini डेटा को इस फ्लैट प्रारूप में बदल देगा:

owner|name|John Doe
owner|organization|Acme Widgets Inc.
database|server|192.0.2.62
database|port|143
database|file|payroll.dat

इसलिए हर लाइन में सेक्शन के नाम का उपयोग करके sed, awkया पार्स करना आसान होगा read

क्रेडिट और स्रोत: शेल स्क्रिप्ट , माइकल ग्रुएनवाल्ड के लिए कॉन्फ़िगरेशन फ़ाइलें


वैकल्पिक रूप से, आप इस प्रोजेक्ट का उपयोग कर सकते हैं: chilladx/config-parserकॉन्फ़िगरेशन पार्सर का उपयोग करके sed


यह भी खूब रही! मैं इसे इस तरह चपटा करने के बारे में सोच रहा था, लेकिन यह मील की दूरी पर है जो मैं एक साथ हैक करने वाला था!
18:00

6

आप crudiniini मान प्राप्त करने के लिए उपकरण का उपयोग कर सकते हैं , उदाहरण के लिए:

DATABASE_VERSION=$(crudini --get parameters.ini '' database_version)

ध्यान दें कि यह पायथन पर आधारित है, इसलिए उदाहरण के लिए एम्बेडेड लिनक्स अनुप्रयोगों के लिए उपयुक्त नहीं हो सकता है।
क्रेग मैकक्वीन

यह मानक फेडोरा रेपो (31 के साथ परीक्षण) का हिस्सा है। yum install crudini
shrewmouse

5

शेल स्क्रिप्ट्स से आईएनआई फाइलों को पढ़ने के लिए (मेरे जैसे) लोगों के लिए (शेल पढ़ें, बैश नहीं) - मैंने थोड़ा हेल्पर लाइब्रेरी खटखटाया है जो ठीक यही करने की कोशिश करता है:

https://github.com/wallyhall/shini (MIT लाइसेंस, कृपया इसे अपने साथ रखें। मैं ऊपर इनलाइन सहित जुड़ा हुआ हूं क्योंकि कोड काफी लंबा है।)

sedऊपर बताई गई सरल लाइनों की तुलना में यह कुछ अधिक "जटिल" है - लेकिन बहुत समान आधार पर काम करता है।

फ़ंक्शन एक फ़ाइल लाइन-बाय-लाइन में पढ़ता है - अनुभाग मार्कर ( [section]) और कुंजी / मूल्य घोषणाओं ( key=value) की तलाश में।

अंततः आपको अपने स्वयं के फ़ंक्शन - अनुभाग, कुंजी और मूल्य पर कॉलबैक मिलता है।


@CraigMcQueen - मैंने आज रात कुछ अल्फा-गुणवत्ता वाले लेखन समर्थन जोड़े हैं। यह कल्पना के किसी भी खंड द्वारा "पूर्ण" नहीं है!
वैली

प्रतिभाशाली! :-) मेजर
जोनाथन

5

अन्य पायथन जवाबों के समान, आप -cकमांड लाइन पर दिए गए पायथन बयानों के अनुक्रम को निष्पादित करने के लिए ध्वज का उपयोग कर सकते हैं :

$ python3 -c "import configparser; c = configparser.ConfigParser(); c.read('parameters.ini'); print(c['parameters.ini']['database_version'])"
20110611142248

इसमें केवल पायथन मानक पुस्तकालय की आवश्यकता का लाभ है और एक अलग स्क्रिप्ट फ़ाइल नहीं लिखने का लाभ है।

या बेहतर पठनीयता के लिए यहां एक दस्तावेज का उपयोग करें, इस प्रकार:

#!/bin/bash
python << EOI
import configparser
c = configparser.ConfigParser()
c.read('params.txt')
print c['chassis']['serialNumber']
EOI

serialNumber=$(python << EOI
import configparser
c = configparser.ConfigParser()
c.read('params.txt')
print c['chassis']['serialNumber']
EOI
)

echo $serialNumber

क्या होगा अगर मैं इस कमांड का उपयोग करके एक पूरे सेक्शन को Array के रूप में हथियाना चाहता हूँ?
देबोपम परुआ

2

कुछ जवाब टिप्पणियों का सम्मान नहीं करते। कुछ वर्गों का सम्मान नहीं करते। कुछ केवल एक सिंटैक्स (केवल ":" या केवल "=") को पहचानते हैं। कुछ अजगर के जवाब मेरे मशीन पर विफल होने के कारण अलग-अलग कैप्शन के माध्यम से या एसआईएस मॉड्यूल आयात करने में विफल रहे। सभी मेरे लिए थोड़े बहुत चर्चित हैं।

इसलिए मैंने अपना स्वयं का लिखा, और यदि आपके पास एक आधुनिक पायथन है, तो आप शायद इसे अपने बैश शेल से बुला सकते हैं। इसमें कुछ सामान्य पायथन कोडिंग सम्मेलनों का पालन करने का लाभ है, और यहां तक ​​कि समझदार त्रुटि संदेश और सहायता प्रदान करता है। इसका उपयोग करने के लिए, इसे कुछ नाम दें जैसे कि myconfig.py (इसे कॉल न करें configparser.py या यह स्वयं को आयात करने का प्रयास कर सकता है), इसे निष्पादन योग्य बनाएं, और इसे कॉल करें

value=$(myconfig.py something.ini sectionname value)

यहाँ लिनक्स पर पायथन 3.5 के लिए मेरा कोड है:

#!/usr/bin/env python3
# Last Modified: Thu Aug  3 13:58:50 PDT 2017
"""A program that Bash can call to parse an .ini file"""

import sys
import configparser
import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="A program that Bash can call to parse an .ini file")
    parser.add_argument("inifile", help="name of the .ini file")
    parser.add_argument("section", help="name of the section in the .ini file")
    parser.add_argument("itemname", help="name of the desired value")
    args = parser.parse_args()

    config = configparser.ConfigParser()
    config.read(args.inifile)
    print(config.get(args.section, args.itemname))

2

जटिल सादगी

आईएनआई फ़ाइल

test.ini

[section1]
name1=value1
name2=value2
[section2]
name1=value_1
  name2  =  value_2

स्क्रिप्ट को पढ़ने और निष्पादित करने के साथ बैश करें

/ Bin / parseini

#!/bin/bash

set +a
while read p; do
  reSec='^\[(.*)\]$'
  #reNV='[ ]*([^ ]*)+[ ]*=(.*)'     #Remove only spaces around name
  reNV='[ ]*([^ ]*)+[ ]*=[ ]*(.*)'  #Remove spaces around name and spaces before value
  if [[ $p =~ $reSec ]]; then
      section=${BASH_REMATCH[1]}
  elif [[ $p =~ $reNV ]]; then
    sNm=${section}_${BASH_REMATCH[1]}
    sVa=${BASH_REMATCH[2]}
    set -a
    eval "$(echo "$sNm"=\""$sVa"\")"
    set +a
  fi
done < $1

फिर एक अन्य स्क्रिप्ट में मैं कमांड के परिणामों को स्रोत करता हूं और किसी भी चर का उपयोग कर सकता हूं

test.sh

#!/bin/bash

source parseini test.ini

echo $section2_name2

अंत में कमांड लाइन से आउटपुट इस प्रकार है

# ./test.sh 
value_2

महान समाधान! धन्यवाद!
माइकल

2

यहाँ मेरा संस्करण है, जो वर्गों को पार्स करता है और इसके साथ एक वैश्विक सहयोगी सरणी g_iniProperties को पॉप्युलेट करता है। ध्यान दें कि यह केवल bash v4.2 और उच्चतर के साथ काम करता है ।

function parseIniFile() { #accepts the name of the file to parse as argument ($1)
    #declare syntax below (-gA) only works with bash 4.2 and higher
    unset g_iniProperties
    declare -gA g_iniProperties
    currentSection=""
    while read -r line
    do
        if [[ $line = [*  ]] ; then
            if [[ $line = [* ]] ; then 
                currentSection=$(echo $line | sed -e 's/\r//g' | tr -d "[]")  
            fi
        else
            if [[ $line = *=*  ]] ; then
                cleanLine=$(echo $line | sed -e 's/\r//g')
                key=$currentSection.$(echo $cleanLine | awk -F: '{ st = index($0,"=");print  substr($0,0,st-1)}')
                value=$(echo $cleanLine | awk -F: '{ st = index($0,"=");print  substr($0,st+1)}')
                g_iniProperties[$key]=$value
            fi
        fi;
    done < $1
}

और यहां ऊपर दिए गए फ़ंक्शन का उपयोग करके एक नमूना कोड है:

parseIniFile "/path/to/myFile.ini"
for key in "${!g_iniProperties[@]}"; do
    echo "Found key/value $key = ${g_iniProperties[$key]}"
done

1

इस स्क्रिप्ट को निम्नानुसार पैरामीटर मिलेंगे:

इसका मतलब है कि अगर आपके पास आई:

pars_ini.ksh <राह ini फ़ाइल> <Ini फ़ाइल में सेक्टर का नाम> <नाम में नाम = वापसी करने के लिए>

जैसे। इसे कैसे कॉल करें:


[ वातावरण ]

एक = एक्स

[DataBase_Sector]

DSN = कुछ


फिर कॉलिंग:

pars_ini.ksh /users/bubu_user/parameters.ini DataBase_Sector DSN

यह निम्नलिखित "कुछ" को पुनः प्राप्त करेगा

स्क्रिप्ट "pars_ini.ksh":

\#!/bin/ksh

\#INI_FILE=path/to/file.ini

\#INI_SECTION=TheSection

\# BEGIN parse-ini-file.sh

\# SET UP THE MINIMUM VARS FIRST

alias sed=/usr/local/bin/sed

INI_FILE=$1

INI_SECTION=$2

INI_NAME=$3

INI_VALUE=""


eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \

    -e 's/;.*$//' \

    -e 's/[[:space:]]*$//' \

    -e 's/^[[:space:]]*//' \

    -e "s/^\(.*\)=\([^\"']*\)$/\1=\"\2\"/" \

   < $INI_FILE  \

    | sed -n -e "/^\[$INI_SECTION\]/,/^\s*\[/{/^[^;].*\=.*/p;}"`


TEMP_VALUE=`echo "$"$INI_NAME`

echo `eval echo $TEMP_VALUE`

1

मैंने अपनी बैश स्क्रिप्ट में शामिल करने के लिए एक त्वरित और आसान अजगर स्क्रिप्ट लिखी।

उदाहरण के लिए, आपकी ini फ़ाइल को कॉल किया जाता है food.ini और फ़ाइल में आपके पास कुछ खंड और कुछ लाइनें हो सकती हैं:

[FRUIT]
Oranges = 14
Apples = 6

इस छोटी 6 पंक्ति पायथन स्क्रिप्ट की प्रतिलिपि बनाएँ और इसे इस रूप में सहेजें configparser.py

#!/usr/bin/python
import configparser
import sys
config = configparser.ConfigParser()
config.read(sys.argv[1])
print config.get(sys.argv[2],sys.argv[3])

अब, आपकी बैश स्क्रिप्ट में आप उदाहरण के लिए ऐसा कर सकते हैं।

OrangeQty=$(python configparser.py food.ini FRUIT Oranges)

या

ApplesQty=$(python configparser.py food.ini FRUIT Apples)
echo $ApplesQty

यह निर्धारित करता है:

  1. आपने पायथन स्थापित किया है
  2. आपके पास configparser पुस्तकालय स्थापित है (यह एक std python स्थापना के साथ आना चाहिए)

आशा है कि यह मदद करता है : ¬)


मैं एक ऐसी चीज की तलाश में था, जो मैंने अभी तक की हो, इसलिए मैंने उदाहरण का पालन किया और यह ठीक काम करती है। मैं भूल गया मैंने यह लिखा था !!!! मैंने अपने लिए वोट देने की कोशिश की, लेकिन अफसोस, मैंने अपने लिए वोट नहीं दिया !!! हा हा
joe_evans

0

वन-लाइनर का मेरा संस्करण

#!/bin/bash
#Reader for MS Windows 3.1 Ini-files
#Usage: inireader.sh

# e.g.: inireader.sh win.ini ERRORS DISABLE
# would return value "no" from the section of win.ini
#[ERRORS]
#DISABLE=no
INIFILE=$1
SECTION=$2
ITEM=$3
cat $INIFILE | sed -n /^\[$SECTION\]/,/^\[.*\]/p | grep "^[:space:]*$ITEM[:space:]*=" | sed s/.*=[:space:]*//

0

बस अपने खुद के पार्सर लिखना समाप्त कर दिया। मैंने यहां पाए गए विभिन्न पार्सर का उपयोग करने की कोशिश की, कोई भी ksh93 (AIX) और बैश (लिनक्स) दोनों के साथ काम नहीं करता है।

यह पुरानी प्रोग्रामिंग शैली है - लाइन द्वारा पार्सिंग लाइन। बहुत तेज है क्योंकि यह कुछ बाहरी आदेशों का उपयोग करता है। सरणी के गतिशील नाम के लिए आवश्यक सभी eval के कारण थोड़ा धीमा।

Ini समर्थन 3 विशेष वाक्यविन्यास:

  • शामिलफाइल = आईएनआई फ़ाइल -> एक अतिरिक्त आईआईएल फ़ाइल लोड करें। कई फाइलों में आईआईएन को विभाजित करने के लिए उपयोगी है, या कॉन्फ़िगरेशन के कुछ टुकड़े का फिर से उपयोग करें
  • शामिल = निर्देशिका -> शामिल के रूप में ही, लेकिन एक पूरी निर्देशिका शामिल हैं
  • शामिल करना = अनुभाग -> एक मौजूदा अनुभाग को वर्तमान अनुभाग में कॉपी करें।

मैं बहुत जटिल, फिर से प्रयोग करने योग्य आईएनई फाइल करने के लिए सभी थॉट्स सिंटैक्स का उपयोग करता था। नए ओएस स्थापित करते समय उत्पादों को स्थापित करने के लिए उपयोगी - हम ऐसा बहुत कुछ करते हैं।

मानों को $ {ini [$ अनुभाग। $ आइटम]} के साथ पहुँचा जा सकता है। इसे कॉल करने से पहले सरणी को परिभाषित किया जाना चाहिए।

मज़े करो। आशा है कि यह किसी और के लिए उपयोगी है!

function Show_Debug {
    [[ $DEBUG = YES ]] && echo "DEBUG $@"
    }

function Fatal {
    echo "$@. Script aborted"
    exit 2
    }
#-------------------------------------------------------------------------------
# This function load an ini file in the array "ini"
# The "ini" array must be defined in the calling program (typeset -A ini)
#
# It could be any array name, the default array name is "ini".
#
# There is heavy usage of "eval" since ksh and bash do not support
# reference variable. The name of the ini is passed as variable, and must
# be "eval" at run-time to work. Very specific syntax was used and must be
# understood before making any modifications.
#
# It complexify greatly the program, but add flexibility.
#-------------------------------------------------------------------------------

function Load_Ini {
    Show_Debug "$0($@)"
    typeset ini_file="$1"
# Name of the array to fill. By default, it's "ini"
    typeset ini_array_name="${2:-ini}"
    typeset section variable value line my_section file subsection value_array include_directory all_index index sections pre_parse
    typeset LF="
"
    if [[ ! -s $ini_file ]]; then
        Fatal "The ini file is empty or absent in $0 [$ini_file]"
    fi

    include_directory=$(dirname $ini_file)
    include_directory=${include_directory:-$(pwd)}

    Show_Debug "include_directory=$include_directory"

    section=""
# Since this code support both bash and ksh93, you cannot use
# the syntax "echo xyz|while read line". bash doesn't work like
# that.
# It forces the use of "<<<", introduced in bash and ksh93.

    Show_Debug "Reading file $ini_file and putting the results in array $ini_array_name"
    pre_parse="$(sed 's/^ *//g;s/#.*//g;s/ *$//g' <$ini_file | egrep -v '^$')"
    while read line; do
        if [[ ${line:0:1} = "[" ]]; then # Is the line starting with "["?
# Replace [section_name] to section_name by removing the first and last character
            section="${line:1}"
            section="${section%\]}"
            eval "sections=\${$ini_array_name[sections_list]}"
            sections="$sections${sections:+ }$section"
            eval "$ini_array_name[sections_list]=\"$sections\""
            Show_Debug "$ini_array_name[sections_list]=\"$sections\""
            eval "$ini_array_name[$section.exist]=YES"
            Show_Debug "$ini_array_name[$section.exist]='YES'"
        else
            variable=${line%%=*}   # content before the =
            value=${line#*=}       # content after the =

            if [[ $variable = includefile ]]; then
# Include a single file
                Load_Ini "$include_directory/$value" "$ini_array_name"
                continue
            elif [[ $variable = includedir ]]; then
# Include a directory
# If the value doesn't start with a /, add the calculated include_directory
                if [[ $value != /* ]]; then
                    value="$include_directory/$value"
                fi
# go thru each file
                for file in $(ls $value/*.ini 2>/dev/null); do
                    if [[ $file != *.ini ]]; then continue; fi
# Load a single file
                    Load_Ini "$file" "$ini_array_name"
                done
                continue
            elif [[ $variable = includesection ]]; then
# Copy an existing section into the current section
                eval "all_index=\"\${!$ini_array_name[@]}\""
# It's not necessarily fast. Need to go thru all the array
                for index in $all_index; do
# Only if it is the requested section
                    if [[ $index = $value.* ]]; then
# Evaluate the subsection [section.subsection] --> subsection
                        subsection=${index#*.}
# Get the current value (source section)
                        eval "value_array=\"\${$ini_array_name[$index]}\""
# Assign the value to the current section
# The $value_array must be resolved on the second pass of the eval, so make sure the
# first pass doesn't resolve it (\$value_array instead of $value_array).
# It must be evaluated on the second pass in case there is special character like $1,
# or ' or " in it (code).
                        eval "$ini_array_name[$section.$subsection]=\"\$value_array\""
                        Show_Debug "$ini_array_name[$section.$subsection]=\"$value_array\""
                    fi
                done
            fi

# Add the value to the array
            eval "current_value=\"\${$ini_array_name[$section.$variable]}\""
# If there's already something for this field, add it with the current
# content separated by a LF (line_feed)
            new_value="$current_value${current_value:+$LF}$value"
# Assign the content
# The $new_value must be resolved on the second pass of the eval, so make sure the
# first pass doesn't resolve it (\$new_value instead of $new_value).
# It must be evaluated on the second pass in case there is special character like $1,
# or ' or " in it (code).
            eval "$ini_array_name[$section.$variable]=\"\$new_value\""
            Show_Debug "$ini_array_name[$section.$variable]=\"$new_value\""
        fi
    done  <<< "$pre_parse"
    Show_Debug "exit $0($@)\n"
    }

0

यह कार्यान्वयन उपयोग करता है awkऔर इसके निम्नलिखित लाभ हैं:

  1. केवल पहली मिलान प्रविष्टि लौटाएगा
  2. उन लाइनों को अनदेखा करता है जो एक से शुरू होती हैं ;
  3. ट्रिम व्हाट्सएप का नेतृत्व और अनुगमन करते हैं, लेकिन आंतरिक व्हाट्सएप नहीं

प्रारूपित संस्करण :

awk -F '=' '/^\s*database_version\s*=/ {
            sub(/^ +/, "", $2);
            sub(/ +$/, "", $2);
            print $2;
            exit;
          }' parameters.ini

वन-लाइनर :

awk -F '=' '/^\s*database_version\s*=/ { sub(/^ +/, "", $2); sub(/ +$/, "", $2); print $2; exit; }' parameters.ini

0

जब मैं बेस 64 में पासवर्ड का उपयोग करता हूं, तो मैं विभाजक डालता हूं: "" क्योंकि बेस 64 स्ट्रिंग में "=" हो सकता है। उदाहरण के लिए (मैं उपयोग ksh):

> echo "Abc123" | base64
QWJjMTIzCg==

में parameters.iniलाइन डाल pass:QWJjMTIzCg==, और अंत में:

> PASS=`awk -F":" '/pass/ {print $2 }' parameters.ini | base64 --decode`
> echo "$PASS"
Abc123

यदि पंक्ति में रिक्त स्थान हैं जैसे उन्हें ट्रिम करने के लिए "pass : QWJjMTIzCg== "जोड़ें | tr -d ' ':

> PASS=`awk -F":" '/pass/ {print $2 }' parameters.ini | tr -d ' ' | base64 --decode`
> echo "[$PASS]"
[Abc123]

0

यह सिस्टम पर्ल का उपयोग करता है और नियमित अभिव्यक्ति को साफ करता है:

cat parameters.ini | perl -0777ne 'print "$1" if /\[\s*parameters\.ini\s*\][\s\S]*?\sdatabase_version\s*=\s*(.*)/'

0

एक अन्य उत्तर के बीच "करेन गैब्रिएलियन" का उत्तर सबसे अच्छा था, लेकिन कुछ वातावरणों में जो हमारे पास नहीं थे, जैसे कि विशिष्ट व्यस्त बॉक्स की तरह, मैंने नीचे दिए गए कोड द्वारा उत्तर को बदल दिया।

trim()
{
    local trimmed="$1"

    # Strip leading space.
    trimmed="${trimmed## }"
    # Strip trailing space.
    trimmed="${trimmed%% }"

    echo "$trimmed"
}


  function parseIniFile() { #accepts the name of the file to parse as argument ($1)
        #declare syntax below (-gA) only works with bash 4.2 and higher
        unset g_iniProperties
        declare -gA g_iniProperties
        currentSection=""
        while read -r line
        do
            if [[ $line = [*  ]] ; then
                if [[ $line = [* ]] ; then 
                    currentSection=$(echo $line | sed -e 's/\r//g' | tr -d "[]")  
                fi
            else
                if [[ $line = *=*  ]] ; then
                    cleanLine=$(echo $line | sed -e 's/\r//g')
                    key=$(trim $currentSection.$(echo $cleanLine | cut -d'=' -f1'))
                    value=$(trim $(echo $cleanLine | cut -d'=' -f2))
                    g_iniProperties[$key]=$value
                fi
            fi;
        done < $1
    }

मुझे पूरी तरह से यकीन नहीं है कि यह कितनी संभावना है कि awk गायब है, लेकिन sed, cut और अपेक्षाकृत अधिक आधुनिक बैश जैसे सिंटैक्स उपलब्ध हैं।
ओन्ड्रेज के।

अधिकांश प्रारंभिक रूट फाइल सिस्टम शेल स्क्रिप्ट के रूप में / linuxrc या / init को लागू करते हैं और इस प्रकार कुछ आवश्यक उपयोगकर्ता-अंतरिक्ष उपयोगिताओं के साथ एक न्यूनतम शेल (आमतौर पर / बिन / राख) शामिल हैं
एहसान अहमदी

ज़रूर। मैं थोड़ा आश्चर्यचकित हूं कि आप अपने व्यस्त बॉक्स को awk के बिना बनाएंगे, लेकिन फिर भी विभिन्न "बशीज़" के लिए सेड, कट और समर्थन के साथ। ऐसा नहीं है कि यह संभव नहीं होगा, बस मुझे आश्चर्य होता है। ;)
Ondrej K.

अन्य उपकरण awk की तुलना में अधिक हल्का है। यदि आप ubuntu distro में initramfs-tools के साथ initramfs में स्क्रिप्ट लिखते हैं, तो आप पाएंगे कि आपके पास awk नहीं है और अन्य उपकरण जैसे sed, grep ... भी न्यूनतम संचालन में हैं।
एहसान अहमदी

निश्चित रूप से, मैं GNU awk या अन्य पूर्ण ब्लोक awk के बारे में बात नहीं कर रहा हूँ, बस यह सोच रहा हूँ कि कोई भी व्यस्त awx सपोर्ट को शामिल करने के लिए कॉन्फ़िगर करने से कितना बचाता है (esp। दिए गए अन्य बिट्स को उस कॉन्फिगर से नहीं निकाला गया है)। हो सकता है कि * बंटू इनिट्र्ड में ऐसा ही एक हो। बस कॉम्बो / पसंद के बारे में सोच रहा था।
ओन्द्रेज के।

0

यदि पायथन उपलब्ध है, तो निम्नलिखित सभी अनुभागों, कुंजियों और मूल्यों को पढ़ेगा और उन्हें "[अनुभाग] _ [कुंजी]" प्रारूप के बाद उनके नामों के साथ चर में बचाएगा। पायथन ठीक से .ini फाइलें पढ़ सकता है, इसलिए हम इसका उपयोग करते हैं।

#!/bin/bash

eval $(python3 << EOP
from configparser import SafeConfigParser

config = SafeConfigParser()
config.read("config.ini"))

for section in config.sections():
    for (key, val) in config.items(section):
        print(section + "_" + key + "=\"" + val + "\"")
EOP
)

echo "Environment_type:  ${Environment_type}"
echo "Environment_name:  ${Environment_name}"

config.ini

[Environment]
  type                = DEV
  name                = D01

0

आप CSI पार्सर xsv का उपयोग INI डेटा पार्स करने के रूप में कर सकते हैं ।

cargo install xsv
$ cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
$ xsv select -d "=" - <<< "$( cat /etc/*release )" | xsv search --no-headers --select 1 "DISTRIB_CODENAME" | xsv select 2
xenial

या एक फ़ाइल से।

$ xsv select -d "=" - file.ini | xsv search --no-headers --select 1 "DISTRIB_CODENAME" | xsv select 2

0

यदि वर्गों का उपयोग करते हैं, तो यह काम करेगा:

उदाहरण कच्चे उत्पादन:

$ ./settings
[section]
SETTING_ONE=this is setting one
SETTING_TWO=This is the second setting
ANOTHER_SETTING=This is another setting

Regexp पार्सिंग:

$ ./settings | sed -n -E "/^\[.*\]/{s/\[(.*)\]/\1/;h;n;};/^[a-zA-Z]/{s/#.*//;G;s/([^ ]*) *= *(.*)\n(.*)/\3_\1='\2'/;p;}"
section_SETTING_ONE='this is setting one'
section_SETTING_TWO='This is the second setting'
section_ANOTHER_SETTING='This is another setting'

अब सभी एक साथ:

$ eval "$(./settings | sed -n -E "/^\[.*\]/{s/\[(.*)\]/\1/;h;n;};/^[a-zA-Z]/{s/#.*//;G;s/([^ ]*) *= *(.*)\n(.*)/\3_\1='\2'/;p;}")"
$ echo $section_SETTING_TWO
This is the second setting

0

मेरे पास एक अच्छा लाइनर है (आपके पास स्थापित phpऔर jqस्थापित करना):

cat file.ini | php -r "echo json_encode(parse_ini_string(file_get_contents('php://stdin'), true, INI_SCANNER_RAW));" | jq '.section.key'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.