쉘 스크립트 내에서 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섹션에서 읽을 행 수는 어디에 있습니까 ? 교체 source로 cat디버그.

  • 구문 분석 오류가있는 경우 다음을 추가하여 무시하십시오. 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_file 에 my_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.