【问题标题】:Parsing .ini file in bash在 bash 中解析 .ini 文件
【发布时间】:2018-08-30 04:45:26
【问题描述】:

我有一个下面的属性文件,并想按如下所述对其进行解析。请帮忙做这件事。

我创建的

.ini 文件:

[Machine1]

app=version1


[Machine2]

app=version1

app=version2

[Machine3]

app=version1
app=version3

我正在寻找一个应该像这样解析ini文件的解决方案

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

谢谢。

【问题讨论】:

    标签: bash ini


    【解决方案1】:

    试试:

    $ 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
    

    它是如何工作的

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

      如果任何行以[ 开头,我们将该行保存在变量prefix 中,然后跳过其余命令并跳转到next 行。

    • $1{print prefix $0}

      如果当前行不为空,我们打印当前行的前缀。

    添加空格

    在任何出现的= 周围添加空格:

    $ 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
    

    这通过使用= 作为输入的字段分隔符和= 作为输出的字段分隔符来工作。

    【讨论】:

      【解决方案2】:

      你可以试试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】:

        我喜欢@John1024 的回答。我正是在寻找那个。我创建了一个 bash 函数,它允许我根据他的想法查找部分或特定键:

        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
        }
        

        所以将其作为 file.ini

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

        然后产生以下结果

        $ 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
        

        再次感谢@John1024 的回答,我正在努力创建一个支持部分的简单 bash ini 解析器。

        使用 GNU bash 在 Mac 上测试,版本 5.0.0(1)-release (x86_64-apple-darwin18.2.0)

        【讨论】:

          【解决方案4】:

          这里有很好的答案。我对@davfive 的功能进行了一些修改,以使其更适合我的用例。此版本基本相同,只是它允许在 = 字符之前和之后使用空格,并允许值中包含空格。

          # Get values from a .ini file
          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 "^\\s*\[" | sed -e "s#\[##g" | sed -e "s#\]##g"); do
                      echo $section
                  done
                  return 0
              fi
              
              local section=$2
              local key
              [ $# -eq 3 ] && key=$3
              
              # This awk line turns ini sections => [section-name]key=value
              local lines=$(awk '/\[/{prefix=$0; next} $1{print prefix $0}' $inifile)
              lines=$(echo "$lines" | sed -e 's/[[:blank:]]*=[[:blank:]]*/=/g')
              while read -r line ; 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 <<<"$lines"
          }
          

          【讨论】:

            猜你喜欢
            • 2012-11-18
            • 1970-01-01
            • 2021-01-06
            • 2012-09-24
            • 2020-06-16
            • 2019-03-09
            • 2010-09-29
            • 1970-01-01
            • 2013-02-06
            相关资源
            最近更新 更多