Parsing .ini file in bash

旧街凉风 提交于 2019-12-24 14:08:36

问题


I have a below properties file and would like to parse it as mentioned below. Please help in doing this.

.ini file which I created :

[Machine1]

app=version1


[Machine2]

app=version1

app=version2

[Machine3]

app=version1
app=version3

I am looking for a solution in which ini file should be parsed like

[Machine1]app = version1
[Machine2]app = version1
[Machine2]app = version2
[Machine3]app = version1
[Machine3]app = version3

Thanks.


回答1:


Try:

$ awk '/\[/{prefix=$0; next} $1{print prefix $0}' file.ini
[Machine1]app=version1
[Machine2]app=version1
[Machine2]app=version2
[Machine3]app=version1
[Machine3]app=version3

How it works

  • /\[/{prefix=$0; next}

    If any line begins with [, we save the line in the variable prefix and then we skip the rest of the commands and jump to the next line.

  • $1{print prefix $0}

    If the current line is not empty, we print the prefix followed by the current line.

Adding spaces

To add spaces around any occurrence of =:

$ awk -F= '/\[/{prefix=$0; next} $1{$1=$1; print prefix $0}' OFS=' = ' file.ini
[Machine1]app = version1
[Machine2]app = version1
[Machine2]app = version2
[Machine3]app = version1
[Machine3]app = version3

This works by using = as the field separator on input and = as the field separator on output.




回答2:


You can try using awk:

 awk '/\[[^]]*\]/{          # Match pattern like [...]
        a=$1;next           # store the pattern in a
      } 
      NF{                   # Match non empty line
        gsub("=", " = ")    # Add space around the = character
        print a $0          # print the line
     }' file



回答3:


I love @John1024's answer. I was looking for exactly that. I have created a bash function which allows me to lookup sections or specific keys based on his idea:

function iniget() {
  if [[ $# -lt 2 || ! -f $1 ]]; then
    echo "usage: iniget <file> [--list|<section> [key]]"
    return 1
  fi
  local inifile=$1

  if [ "$2" == "--list" ]; then
    for section in $(cat $inifile | grep "\[" | sed -e "s#\[##g" | sed -e "s#\]##g"); do
      echo $section
    done
    return 0
  fi

  local section=$2
  local key
  [ $# -eq 3 ] && key=$3

  # https://stackoverflow.com/questions/49399984/parsing-ini-file-in-bash
  # This awk line turns ini sections => [section-name]key=value
  local lines=$(awk '/\[/{prefix=$0; next} $1{print prefix $0}' $inifile)
  for line in $lines; do
    if [[ "$line" = \[$section\]* ]]; then
      local keyval=$(echo $line | sed -e "s/^\[$section\]//")
      if [[ -z "$key" ]]; then
        echo $keyval
      else          
        if [[ "$keyval" = $key=* ]]; then
          echo $(echo $keyval | sed -e "s/^$key=//")
        fi
      fi
    fi
  done
}

So given this as file.ini

[Machine1]
app=version1
[Machine2]
app=version1
app=version2
[Machine3]
app=version1
app=version3

then the following results are produced

$ iniget file.ini --list
Machine1
Machine2
Machine3

$ iniget file.ini Machine3
app=version1
app=version3

$ iniget file.ini Machine1 app
version1

$ iniget file.ini Machine2 app
version2
version3

Again, thanks to @John1024 for his answer, I was pulling my hair out trying to create a simple bash ini parser that supported sections.

Tested on Mac using GNU bash, version 5.0.0(1)-release (x86_64-apple-darwin18.2.0)



来源:https://stackoverflow.com/questions/49399984/parsing-ini-file-in-bash

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!