쉘 스크립트 내에서 INI 값을 어떻게 가져 옵니까?


97

다음과 같은 parameters.ini 파일이 있습니다.

[parameters.ini]
    database_user    = user
    database_version = 20110611142248

bash 쉘 스크립트 내에서 parameters.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
이 답변 중 섹션을 전혀 존중하지 않는 것이 있습니까?
ManuelSchneid3r

답변:


83

그 라인을 grepping하고 awk를 사용하는 것은 어떻습니까?

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

6
여기에는 '='뒤에 공백이 포함됩니다.

10
공백을 자르려면 | tr -d ' '끝에 추가 하십시오.
kenorb

22
이것은 정말 좋은 해결책이 아닙니다. 각각 'database_version'변수가있는 2 개의 [parameters.ini] 섹션이 있다고 생각하십시오. 그런 다음 두 번 값을 얻습니다.
nerdoc

4
위의 처리하지 많은 첨단 경우가 있기 때문에 예, crudini 같은 전문 INI 파서를 고려하시기 바랍니다
pixelbeat

3
기본 ini 파일에 여전히 유용하고 빠릅니다.
Cyril N.

51

다음과 같이 bash 원시 구문 분석기를 사용하여 ini 값을 해석 할 수 있습니다.

$ source <(grep = file.ini)

샘플 파일 :

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

변수에 액세스하려면 간단히 인쇄합니다 echo $var1.. 위에 표시된대로 배열을 사용할 수도 있습니다 (echo ${IPS[@]} ).

단일 값만 원하는 경우 grep 만하면됩니다.

source <(grep var1 file.ini)

데모를 보려면 asciinema에서이 녹음을 확인하십시오 .

데이터를 구문 분석하기 위해 외부 라이브러리가 필요하지 않기 때문에 간단하지만 몇 가지 단점이 있습니다. 예를 들면 :

  • =(변수 이름과 값) 사이에 공백이 있으면 먼저 공백 을 잘라야합니다.

      $ 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섹션에서 읽을 행 수는 어디에 있습니까 ? 교체 sourcecat디버그.

  • 구문 분석 오류가있는 경우 다음을 추가하여 무시하십시오. 2>/dev/null

또한보십시오:


1
하지만 ... source <(grep = <(grep -A5 '\[section-b\]' file.ini))이것은 작동하지 않습니다 : [sec a] a = 1 b = 2 c = 3 [sec b] a = 2 b = 3 [sec c] a = 0. 어디 라인 명확한 규칙이 없습니다
Psychozoic

소스를 사용하려고했지만 $ var1을 에코하면 아무것도 반환하지 않습니다. 왜?
A. Gh

@ A.Gh 잘 모르겠습니다. Bash 셸을 사용하고 있는지 확인하십시오. 참조 : asciinema.org/a/306481
kenorb

이것은 우아했지만 OS X (Catalina)에서 작동하지 못했습니다. zsh (현재 기본 셸)의 명령 프롬프트에서 작동하지만 스크립트에 넣으면 오류가 발생 syntax error near unexpected token '('합니다. bash를 사용하면 프롬프트와 스크립트 모두에서 조용히 실패합니다.
MiRin

29

Bash는 이러한 파일에 대한 파서를 제공하지 않습니다. 분명히 awk 명령이나 sed 호출 몇 개를 사용할 수 있지만 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"

Bash ini-parser는 The Old School DevOps 블로그 사이트 에서 찾을 수 있습니다 .


3
이 링크가 질문에 답할 수 있지만 여기에 답변의 필수 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 무효화 될 수 있습니다.
alecxe

8
나는 일반적으로 이와 같은 코멘트를하는 사람이다. 모든 내가 말할 수있는 내가 :-) 젊은 바보이다
프레드릭 Pihl

1
이 스 니펫이 마음에 들면
albfan

3
올바르게 작동하려면 cfg.parser 대신 cfg_parser를 사용해야합니다
Wes

1
오타 : "cfg.parser"는 "cfg_parser"여야합니다.
Setop

26

섹션을 고려한 Sed one-liner. 예제 파일 :

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

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

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

section2에서 param2를 원한다고 가정하십시오. 다음을 실행하십시오.

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

너에게 줄 것이다

def

3
sed -nr "/ ^ \ [SECTION2 \] / {: l /^\s*[^#].*/ p; n; / ^ \ [/ q; bl;}"file.conf # 전체 섹션 가져 오기 [SECTION2] 및 # 해시 스타일 주석 행이있는 .conf 스타일 파일에 대한 주석 없음. 그런 다음 하나의 매개 변수 만 원하면 paramname에 대해 grep하십시오.
gaoithe

다음 줄을 읽는 것보다 sed 범위 주소를 사용하는 것이 좋습니다."/^\[section2\]/,/^\[/{...}"
basin

1
맥에있는 경우 : brew install gnu-sed다음 사용 gsed(그렇지 sed: illegal option -- r)
frnhr

sed -nr "/^\[SECTION2\]/ { :l /^\s*[^#].*/ p; n; /^\[/ q; b l; }" 표현이 어떻게 작동 하는지 설명해 주 시겠습니까? 감사합니다
foo_l

22

.ini 파일을 bash 본문에 포함하기 만하면됩니다.

example.ini 파일 :

DBNAME=test
DBUSER=scott
DBPASSWORD=tiger

example.sh 파일

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

2
이것은 선택된 답변이어야합니다. file.properties와 함께 작동하며 내결함성이 있습니다 (내부에 빈 줄이있는 파일). 감사합니다
안토니

17
INI 파일의 [섹션] 부분을 처리하지 않습니다.
Setop

이것이 최고의 답변입니다!
JavaSheriff

17
바라건대 아무도 ini 파일에 "rm -rf /"를 추가하지 않았
으면

1
서브 쉘에서 훨씬 안전합니다 : $ (. example.ini는, $ DBNAME 에코)
리치 피엘 러 레 메르

14

지금까지 본 모든 솔루션은 주석 처리 된 줄에도 적용되었습니다. 이것은 주석 코드가 ;다음 과 같으면 그렇지 않습니다 .

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

2
a) 주석 처리 된 줄을 처리합니다. b) 단순 :)
Sudar

1
이것은 대단합니다, ty @PenguinLust! 사용법 : 1. 세미콜론 접두사로 전체 줄 주석 허용 (인라인 줄 끝 주석은 허용되지 않음) 2. 공백은 결과에서 제거되지 않습니다 (따라서 ini 파일에 'a = 1'이있는 경우 스크립트의 'a'검색은 '1'로 평가됩니다).
AnneTheAgile 2014-08-04

1
공백을 자르려면 | tr -d ' '끝에 추가 하십시오.
kenorb

이것은 제안 된 답변과 동일한 문제가 있습니다. "database_version"의 모든 인스턴스를 검색합니다.
Nubcake

12

가능한 솔루션 중 하나

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

8

ini 스타일 my_filemy_key 값을 표시합니다 .

sed -n -e 's/^\s*my_key\s*=\s*//p' my_file
  • -n -기본적으로 아무것도 인쇄하지 않음
  • -e -표현식 실행
  • s/PATTERN//p -패턴에서이 패턴을 따르는 모든 것을 표시합니다.
  • ^ -패턴은 줄의 시작 부분에서 시작됩니다.
  • \s -공백 문자
  • * -0 개 또는 다수 (공백 문자)

예:

$ 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

그래서:

행이 0 개 이상의 공백 문자로 시작하고 그 뒤에 my_key 문자열 , 0 개 이상의 공백 문자, 등호, 0 개 이상의 공백 문자가 차례로 오는 패턴을 찾습니다 . 해당 패턴에 따라 해당 줄에 나머지 콘텐츠를 표시합니다.


귀하의 예제는 bar적어도 Unix / OSX에서 작동하지 않습니다 ( 인쇄 되지 않음 ).
kenorb

7

sed

sed특히 다음과 같은 섹션 이름이있는 경우 ini 구성 파일을 구문 분석하는 데 사용할 수 있습니다 .

# 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모든 라인에 섹션 이름을함으로써.

크레딧 및 출처 : 셸 스크립트 용 구성 파일 , Michael Grünewald


또는이 프로젝트를 사용할 수 있습니다 : chilladx/config-parser, sed.


대단합니다! 나는 그것을 그렇게 평평하게 할 것을 생각하고 있었지만 이것은 내가 함께 해킹하려고했던 것보다 훨씬 더 많습니다!
grinch

6

crudini도구를 사용 하여 ini 값을 가져올 수 있습니다 . 예 :

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

Python 기반이므로 임베디드 Linux 응용 프로그램에는 적합하지 않을 수 있습니다.
크레이그 맥퀸

이것은 표준 Fedora 저장소의 일부입니다 (31로 테스트 됨). yum install crudini
shrewmouse

5

(나와 같은) 쉘 스크립트 (bash가 아닌 쉘 읽기)에서 INI 파일을 읽으려는 사람들을 위해-정확히 그렇게하려는 작은 도우미 라이브러리를 두 드렸습니다.

https://github.com/wallyhall/shini (MIT 라이센스, 원하는대로 사용하십시오. 코드가 상당히 길기 때문에 인라인으로 포함하여 위에 링크했습니다.)

sed위에서 제안한 간단한 라인 보다 다소 더 "복잡" 하지만 매우 유사한 기준으로 작동합니다.

함수는 파일을 한 줄씩 읽습니다. 섹션 마커 ( [section]) 및 키 / 값 선언 ( key=value)을 찾습니다 .

궁극적으로 섹션, 키 및 값과 같은 자체 함수에 대한 콜백을받습니다.


@CraigMcQueen-오늘 밤 매우 알파 품질의 쓰기 지원을 추가했습니다. 상상력의 확장으로 "완전한"것이 아닙니다!
wally

훌륭한! :-) 주요
조나단

5

다른 Python 답변과 마찬가지로 -c플래그를 사용 하여 명령 줄에 지정된 일련의 Python 문을 실행할 수 있습니다 .

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

이것은 Python 표준 라이브러리 만 필요하다는 장점과 별도의 스크립트 파일을 작성하지 않는 장점이 있습니다.

또는 더 나은 가독성을 위해 here 문서를 사용하십시오.

#!/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

이 명령을 사용하여 전체 섹션을 배열로 가져 오려면 어떻게해야합니까?
Debopam Parua

2

일부 답변은 댓글을 존중하지 않습니다. 일부는 섹션을 존중하지 않습니다. 일부는 하나의 구문 만 인식합니다 ( ":"또는 "="만). 다른 대문자 화 또는 sys 모듈 가져 오기 실패로 인해 일부 Python 답변이 내 컴퓨터에서 실패합니다. 모두 나에게 너무 간결합니다.

그래서 제가 직접 작성했고, 최신 Python이 있다면 아마도 Bash 셸에서 이것을 호출 할 수 있습니다. 일반적인 Python 코딩 규칙 중 일부를 준수하는 이점이 있으며, 합리적인 오류 메시지와 도움말도 제공합니다. 이를 사용하려면 myconfig.py와 같은 이름을 지정하십시오 (configparser.py라고 부르지 마십시오. 또는 자체적으로 가져 오려고 시도 할 수 있음). 실행 가능하게 만들고 다음과 같이 호출하십시오.

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

Linux에서 Python 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

복잡한 단순성

ini 파일

test.ini

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

읽기 및 실행 기능이있는 bash 스크립트

/ 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

훌륭한 솔루션! 감사!
Michael

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

이 스크립트는 다음과 같은 매개 변수를 가져옵니다.

ini가 다음과 같은 경우 의미합니다.

pars_ini.ksh <ini 파일 경로> <Ini 파일의 섹터 이름> <이름의 이름 = 반환 할 값>

예. 그것을 부르는 방법 :


[환경]

a = x

[데이터베이스 _ 섹터]

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

bash 스크립트에 포함 할 빠르고 쉬운 python 스크립트를 작성했습니다.

예를 들어 ini 파일이 호출 food.ini 되고 파일에 일부 섹션과 일부 행이있을 수 있습니다.

[FRUIT]
Oranges = 14
Apples = 6

이 작은 6 줄 Python 스크립트를 복사하여 다음과 같이 저장하십시오. 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])

이제 bash 스크립트에서 예를 들어 이렇게 할 수 있습니다.

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

또는

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

이것은 다음을 전제로합니다.

  1. Python이 설치되어 있습니다.
  2. configparser 라이브러리가 설치되어 있습니다 (표준 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)과 bash (Linux) 둘 다에서 작동하지 않는 것 같습니다.

오래된 프로그래밍 스타일-한 줄씩 구문 분석. 외부 명령을 거의 사용하지 않았기 때문에 매우 빠릅니다. 배열의 동적 이름에 필요한 모든 평가 때문에 약간 느립니다.

ini는 3 가지 특수 구문을 지원합니다.

  • includefile = ini 파일-> 추가 ini 파일을로드합니다. 여러 파일에서 ini를 분할하거나 일부 구성을 재사용하는 데 유용합니다.
  • includedir = directory-> includefile과 동일하지만 전체 디렉토리를 포함합니다.
  • includesection = section-> 기존 섹션을 현재 섹션에 복사합니다.

이 모든 구문을 사용하여 꽤 복잡하고 재사용 가능한 ini 파일을 만들었습니다. 새 OS를 설치할 때 제품을 설치하는 데 유용합니다. 우리는 그렇게 많이합니다.

$ {ini [$ section. $ item]}를 사용하여 값에 액세스 할 수 있습니다. 이것을 호출하기 전에 배열을 정의해야합니다.

즐기세요. 다른 사람에게 유용하기를 바랍니다!

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

base64에서 암호를 사용할 때 base64 문자열에 "="가있을 수 있으므로 구분 기호 ":"를 넣습니다. 예를 들어 (나는 사용 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

다른 답변 중 "Karen Gabrielyan"의 답변이 최고 였지만 일부 환경에서는 일반적인 busybox와 같이 awk가 없습니다. 아래 코드로 답변을 변경했습니다.

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 및 비교적 고급 bash 유사 구문을 사용할 수 있습니다.
Ondrej K.

대부분의 초기 루트 파일 시스템은 / linuxrc가를 구현하거나 / 쉘 스크립트로 초기화하기 때문에 몇 가지 필수적인 사용자 공간 유틸리티와 함께 최소한의 쉘 (보통 / 빈 / 재)를 포함
에산 마디를

확실한. 나는 당신이 awk없이 당신의 busybox를 구축 할 수 있다는 것에 조금 놀랐지 만, 여전히 다양한 "bashisms"에 대한 sed, cut 및 지원을 가지고 있습니다. 가능하지 않다는 게 아니라 그냥 궁금하게 만들뿐입니다. ;)
Ondrej K.

다른 도구는 awk보다 가볍습니다. 우분투 배포판에서 initramfs-tools를 사용하여 initramfs에 스크립트를 작성하면 awk가없고 sed, grep ...와 같은 다른 도구도 최소 작동 상태임을 알 수 있습니다.
Ehsan Ahmadi

물론, 나는 GNU awk 또는 다른 완전한 awk에 대해 이야기하는 것이 아니라 busybox를 awk 지원을 포함하지 않도록 구성함으로써 얼마나 절약 할 수 있는지 궁금합니다. * buntu initrd에 이와 같은 것이있을 수 있습니다. 그저 콤보 / 선택에 대해 궁금합니다.
Ondrej K.

0

Python을 사용할 수있는 경우 다음은 모든 섹션, 키 및 값을 읽고 "[section] _ [key]"형식을 따르는 이름으로 변수에 저장합니다. Python은 .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

CSV 파서 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

정규식 구문 분석 :

$ ./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'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.