使用shell读取ini文件方法步骤

目录
  • 动机
  • .ini 类文件格式
  • 在 shell 脚本中处理 .ini 文件时要执行的操作
  • 假定处理系统
  • 查看部分列表
  • 仅提取特定部分
  • 如何限定 shell 变量名
  • Shell scripting

动机

我决定编写一个脚本来进行干净的 macOS (BSD) / Linux 的初始设置。 我认为有一个 tsukkomi 说“现在大多数发行版都预装了 perl / python”,但我决定使用 Shell 脚本(bash),因为它易于编写进程过程。 但是,用shell语法写各种配置文件是不可读的,所以我决定把配置文件写成.ini文件,用sed处理,然后加载到shell中。 关于使用 sed 解析 .ini 文件,如果你在 google 上搜索会出现各种示例,但我决定将其作为可以处理 .ini 文件(如)的规范,通过引用它们更具可读性。

.ini 类文件格式

  • 在 [section] 中设置节。紧接在 [和紧接之前] 之后的空白字符序列(空格 / 制表符)不被视为部分名称的一部分。 (规定可以在节名及其前后的括号之间放置空格字符。)但是,节名不应包含换行符。
  • 用 parameter = value 设置参数变量及其值。 = 前后可以有空格。假设参数名称不包括=。如果参数名称包含不能在 shell 变量中使用的字符,则在输出的 shell 变量名称中将这些字符替换为 _。
  • 如果行尾有 \,则下一行被视为续行。如果一行的开头有 4 个或更多空格/制表符,则将其视为上一行的续行。
  • 忽略 # ,; 中的行尾作为注释。
  • 忽略不包含 [and’]’ 的行,或在行首以外的位置不包含 = 的行。

在 shell 脚本中处理 .ini 文件时要执行的操作

查看部分列表。

将参数作为 shell 变量读取。 然而,作为一种变体

1. 让特定部分的参数为 shell 变量。 在某些情况下,将其设置为 shell 函数中的局部变量或环境变量。
2. 让所有或部分部分的参数为 shell 变量。 shell变量名是’基于段名的前缀’+‘参数名’。 同样在这种情况下,将其设置为局部变量或环境变量。 基于节名的前缀是通过将节名字符串中的shell变量中不能使用的字符替换为_并在末尾添加_来生成的。

假定处理系统

  • bash
  • BSD sed(我不能使用方便的 GNU sed 扩展,但我想在干净的 macOS 上运行它。)但是,我使用带有 -E 选项的扩展正则表达式。 (因为如果不能使用一个或多个匹配元字符’+',sed 语句就会变长。)

处理连续行和注释似乎有更普遍的用途,所以我单独描述。 通过将代码添加到那里描述的 sample5.sed 来实现上述内容。

查看部分列表

这相对容易。 不要处理与节名格式不匹配的行。 您所要做的就是删除与节名格式和输出相对应的行中的’[‘,’]’ 和不必要的部分。 这时候需要注意的是,换行符不是随便删的,如单独描述的,匹配换行符以外的表达式([^ \ [:space:]]] | [[ : 空白: ]]) 被使用。

:begin
$!N
s/[#;]([^[:space:]]|[[:blank:]])*([^\\[:space:]]|[[:blank:]])(\n)/\3/
s/[#;]([^[:space:]]|[[:blank:]])*(\\)(\n)/\2\3/
$s/[#;]([^[:space:]]|[[:blank:]])*$//
/(\\\n|\n[[:blank:]]{4})/ {
  s/[[:blank:]]*(\\\n|\n[[:blank:]]{4})[[:blank:]]*/ /
  t begin
}
/^[[:blank:]]*\n/ D
/\n[[:blank:]]*$/ {
  s/\n[[:blank:]]*$//
  t begin
}
/^\[([^[:space:]]|[[:blank:]])*\]/! D
s/\[[[:blank:]]*//
s/[[:blank:]]*\]([^[:space:]]|[[:blank:]])*//
P
D

例如,如果您尝试将其作为示例 .ini 文件,

# -*- mode: conf-mode ; -*- \
#;
#; sample .ini file
#;
#;

[tako]
param_a=(1 # 2 3 \
4 5 ### 6 7 
    8 9 # 10
    )

a=b # kani \
# kani \

[kani]
param_a=1
param_b=2

[uni]
param_a=3
param_b=4

[wani]
param_a=5
param_b=6

[hebi]
param_a=9
param_b=10

output example:

% sed -nE -f list_section.sed sample.ini
tako
kani
uni
wani
hebi

仅提取特定部分

下面的示例仅从上面的示例中提取特定部分 (wani) 的行,这些行遵循正确的参数定义格式。如果您找到以节名形式存在的一行,请将节名存储在保留空间中,否则如果保留空间的内容与所需的节名不匹配,则转到下一行。…如果匹配,则检查是否匹配参数格式的定义,去掉空格,本例中添加文本,使其成为shell函数的局部变量,可以总结shell变量定义。在行尾。因为已经变长了,所以加了注释行,但是作为控制结构,对每个处理都进行必要的处理,如果后面的处理没有必要,就直接回到开头. , 应该比较容易理解。

:begin
$!N
# Erase comment strings
s/[#;]([^[:space:]]|[[:blank:]])*([^\\[:space:]]|[[:blank:]])(\n)/\3/
s/[#;]([^[:space:]]|[[:blank:]])*(\\)(\n)/\2\3/
$s/[#;]([^[:space:]]|[[:blank:]])*$//
# Concatenate continuation lines
/(\\\n|\n[[:blank:]]{4})/ {
  s/[[:blank:]]*(\\\n|\n[[:blank:]]{4})[[:blank:]]*/ /
  t begin
}
# Erase blank lines
/^[[:blank:]]*\n/ D
/\n[[:blank:]]*$/ {
  s/\n[[:blank:]]*$//
  t begin
}
# Check section headline and store section name to holdspace
/^([^[:space:]]|[[:blank:]])*\[([^[:space:]]|[[:blank:]])*\]/ {
h
x
s/^([^[:space:]]|[[:blank:]])*\[(([^[:space:]]|[[:blank:]])*)\].*$/\2/g
s/^[[:blank:]]*//g
s/[[:blank:]]$//g
x
D
}
# Skip line if current section is not interested one
x
/^wani$/! { 
  x
  D
}
x
# Print if it is proper parameter definition 
/^(([^[:space:]=]|[[:blank:]])*)=(([^[:space:]]|[[:blank:]])*)/ {
  s/^[[:blank:]]*/local /
  s/[[:blank:]]*=[[:blank:]]*/=/
  s/(([^[:space:]]|[[:blank:]])*)[[:blank:]]*(\n)/\1;\3/
  P
}
D

如何限定 shell 变量名

如关于您想要做什么的部分中所述,您想要添加从部分名称生成的前缀到 shell 变量,或者如果 .ini 文件中的参数名称包含不能在 shell 变量中使用的字符串, 适当转换。 作为一种简单的方法,有多次调用sed并处理的方法,但是如果可以的话,我觉得用一个进程号sed就可以处理更漂亮。 这里最大的限制是 sed 没有一个保存空间。 在高级脚本语言中,可以将文本段划分为多个变量,进行存储、处理和组合。 另一方面,在 sed 的情况下,标准方法似乎是将多个文本作为堆栈保存和使用,并将保留空间作为分隔符并带有换行符。

例如,在下面的示例中,保留空间从第一行开始。

  • 部分名称
  • 带格式化部分名称的前缀
  • 模式空间第一行的备份
  • 模式空间第二行的备份
  • 根据.ini文件中的参数名格式化的Shell变量名

需要决定如何使用它,保持保持空间中的行数不变(下例中为 2 行),并在处理行转换时适当恢复模式空间。 由于交换保持空间和模式空间的命令只有gG和hH,类似的处理可能会重复出现,所以不可否认在1sed的过程中做起来真的很漂亮。

不管怎样,下面是从上面的 sample.ini 文件中提取 wani 和 uni 部分并输出添加了部分名称的 shell 变量的定义语句的示例。 整体控制结构保持简单,并且我添加了注释,所以我希望你能看到重写的地方以提取另一个部分,例如。

# Initialine the hold space: (Single empty line at the beginning)
1 { H ; x ; 
  # Change the expression for the defalut section name and/or variable prefix, here.
  s/^([^[:space:]]|[[:blank:]])*(\n)([^[:space:]]|[[:blank:]])*$/global\2global_/g
  x
}
:begin
$!N
# Erase comment strings
s/[#;]([^[:space:]]|[[:blank:]])*([^\\[:space:]]|[[:blank:]])(\n)/\3/
s/[#;]([^[:space:]]|[[:blank:]])*(\\)(\n)/\2\3/
$s/[#;]([^[:space:]]|[[:blank:]])*$//
# Concatenate continuation lines
/(\\\n|\n[[:blank:]]{4})/ {
  s/[[:blank:]]*(\\\n|\n[[:blank:]]{4})[[:blank:]]*/ / ; t begin
}
# Erase blank lines
/^[[:blank:]]*\n/ D
/\n[[:blank:]]*$/ {
  s/\n[[:blank:]]*$// ; t begin
}
# Check section headline and store section name to holdspace
/^([^[:space:]]|[[:blank:]])*\[([^[:space:]]|[[:blank:]])*\]/ {
  # Remove blackets and extra spaces at first line
  s/^([^[:space:]]|[[:blank:]])*\[(([^[:space:]]|[[:blank:]])*)\](([^[:space:]]|[[:blank:]])*)(\n)/\2\6/g
  s/^[[:blank:]]*//g; s/[[:blank:]]*(\n)/\1/g
  # Store the section name to the hold space, and format stored one for shell variable for the hold space
  h
  x
  s/(\n)([^[:space:]]|[[:blank:]])*$//
  s/([^[:alnum:]_]|$)/_/g
  x
  # Append the section name to the hold space.
  H
  # Remove unused line of the hold space and rearrange the remaining lines.
  x
  s/(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)$/\4\3\1/
  x
  D
}
# Skip line if current section is not interested one
x
/^(wani|uni)(\n)/! { x ; D ; }
x
# Print if it is proper parameter definition 
/^(([^[:space:]=]|[[:blank:]])*)=(([^[:space:]]|[[:blank:]])*)/ {
  # Store current patern space text at the end of the hold space
  H

  # Build shell script variable name and store it at the end of the hold space
  s/(([^[:space:]=]|[[:blank:]])*)=.*$/\1/g
  s/^[[:blank:]]*//
  s/[[:blank:]]*$//
  s/[^[:alnum:]_]/_/g
  # If further rename of the variable name is necessary, put here.

  # Store variable name at the end of the hold space
  H

  # Build parameter variable value and keep it at pattern space
  # At first, Resore the current line text from hold space
  g
  # Remove unused lines.
  s/^(([^[:space:]]|[[:blank:]])*\n){2}//
  s/(\n([^[:space:]]|[[:blank:]])*){2}$//
  # Remove the text other than the parameter value
  s/^([^[:space:]=]|[[:blank:]])*=//g
  # If further formatting of the value is necessary, put here.

  # Append hold space stored date into pattern space
  G
  # Remove unused lines from the pattern space
  s/^(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)/\1\5\9/
  # Rearrance the order of line in the pattern space, it is nessacery because only \1 ...\9 is avaiable
  s/^(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*\n)(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)$/\1\3\8\7\5/

  # Format the output in the first line of the pattern space, and 
  # Restore the next line at the second line of the pattern space
  s/^(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)(\n)(([^[:space:]]|[[:blank:]])*)(\n([^[:space:]]|[[:blank:]])*)$/local \4\7=\1;\9/

  # Clean up hold space
  x
  s/(\n([^[:space:]]|[[:blank:]])*){3}$//
  x
  P
}
D

output example:

% sed -n -E -f pickup_section2.sed sample.ini
local uni_param_a=3;
local uni_param_b=4;
local wani_param_a=5;
local wani_param_b=6;

Shell scripting

每次更改要提取的section或者切换输出格式(sh/csh、shell变量/局部变量/环境变量、变量名前缀的ON/OFF)都要重写sed文件很麻烦,所以命令行我准备了生成 sed 命令作为选项的 shell 脚本。 使用另一篇文章中的模板生成。 对于上面的seds,我还尝试了通过.ini文件的参数变量名(shell变量名)来选择输出。 (但是,如果指定了多个段名和变量名,组合不是唯一的,所以它可能不是一个很有用的功能。)

文件存储:

https://github.com/nanigashi-uji/parse_ini_sh
https://gitlab.com/nanigashi_uji/parse_ini_sh

如何使用

[Usage] % parse_ini.sh -list     file [files ...]
        % parse_ini.sh [options] file [files ...]

[Options]
    -l,--list                       : List sections 
    -S,--sec-select       name      : Section name to select
    -T,--sec-select-regex expr      : Section reg. expr. to select
    -V,--variable-select name       : variable name to select
    -W,--variable-select-regex expr : variable reg. expr. to select
    -L,--local                      : Definition as local variables (B-sh)
    -e,--env                        : Definition as enviromnental variables
    -q,--quot                       : Definition by quoting with double/single-quotation.
    -c,--csh,--tcsh                 : Output for csh statement (default: B-sh)
    -b,--bsh,--bash                 : Output for csh statement (default)
    -s,--sec-prefix                 : add prefix: 'sectionname_' to variable names. 
    -v,--verbose                    : Verbose messages 
    -h,--help                       : Show Help (this message)

output example:

% parse_ini.sh --list sample.ini
tako
kani
uni
wani
hebi

% parse_ini.sh -S kani -L sample.ini
local param_a=1;
local param_b=2;

% parse_ini.sh -S kani -L -s sample.ini
local kani_param_a=1;
local kani_param_b=2;

% parse_ini.sh -S kani -L -e -c sample.ini
setenv param_a 1;
setenv param_b 2;

% parse_ini.sh -S kani -L -e -c -q sample.ini
setenv param_a "1";
setenv param_b "2";

到此这篇关于使用shell读取ini文件方法步骤的文章就介绍到这了,更多相关shell读取ini文件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Shell脚本读取ini配置文件的实现代码2例

    一.简单版 参考stackoverflow的例子,改了一个出来: 复制代码 代码如下: while IFS='= ' read var val do     if [[ $var == \[*] ]]     then         section=$(echo $var | sed 's/^\[\(.*\)\]$/\1/')     elif [[ $val ]]     then         if [ -z $section ];then             declare "${

  • Shell实现读取ini格式配置文件方法

    ini文件格式一般都是由节.键.值三部分组成 格式: [第一节 ] 第一个键 = 值 第二个键 = 第二个值 [第二节 ] 第一个键 = val1,val2,val3 例子: 复制代码 代码如下: [COM] KINGGOO = jb51.net 其实这个作用没那么特别大,但多个shell如果每个配置信息都在shell文件里面写,懂的人还好,半懂+不仔细的人要如何改,改几个地方估计脚本就不能运行了.所以这样单独哪出来比较好些,而且可以多个shell使用一个ini文件(与扩展名无关)来做配置也可以

  • Shell脚本读取标准ini配置文件Demo

    ini DEMO 复制代码 代码如下: [TESTFTP] host=127.0.0.1 name=my pass=mylove type=ftp [TESTSSH] host=127.0.0.1 name=my pass=mylove type=ssh [END] Shell脚本: 复制代码 代码如下: initConf() { HOSTID=$1 CONF=$2 echo "----cat----" cat $CONF \\     | grep -v ^$ \\     | se

  • 使用shell读取ini文件方法步骤

    目录 动机 .ini 类文件格式 在 shell 脚本中处理 .ini 文件时要执行的操作 假定处理系统 查看部分列表 仅提取特定部分 如何限定 shell 变量名 Shell scripting 动机 我决定编写一个脚本来进行干净的 macOS (BSD) / Linux 的初始设置. 我认为有一个 tsukkomi 说“现在大多数发行版都预装了 perl / python”,但我决定使用 Shell 脚本(bash),因为它易于编写进程过程. 但是,用shell语法写各种配置文件是不可读的,

  • Python从文件中读取数据的方法步骤

    一.读取整个文件内容 在读取文件之前,我们先创建一个文本文件resource.txt作为源文件. resource.txt my name is joker, I am 18 years old, How about you? 如何读取文件全部内容,我们编写到reader.py文件中. reader.py with open('resource.txt') as file_obj: content = file_obj.read() print(content) 需要注意的是需要将resourc

  • Python读取ini文件、操作mysql、发送邮件实例

    我是闲的没事干,2014过的太浮夸了,博客也没写几篇,哎~~~ 用这篇来记录即将逝去的2014 python对各种数据库的各种操作满大街都是,不过,我还是喜欢我这种风格的,涉及到其它操作,不过重点还是对数据库的操作.呵~~ Python操作Mysql 首先,我习惯将配置信息写到配置文件,这样修改时可以不用源代码,然后再写通用的函数供调用 新建一个配置文件,就命名为conf.ini,可以写各种配置信息,不过都指明节点(文件格式要求还是较严格的): 复制代码 代码如下: [app_info] DAT

  • 使用正则表达式(regex_replace)模拟读取INI文件

    废话不多说了,直接给大家贴代码了,具体代码如下所示: #include "stdio.h" #include <sstream> #include <iostream> #include <fstream> #include <regex> using namespace std; void Trim(char * str); void lTrim(char * str); void rTrim(char * str); // 测试ssc

  • C 读取ini文件的实例详解

    C 读取ini文件 前言: 在Windows下可以用GetPrivateProfileString或GetPrivateProfileInt方便读取.ini配置文件内容,但是在Linux平台上就一筹莫展了.为了解决该问题,打算用C来读取.ini,即可不受平台的限制了. #define CONF_FILE_PATH "Config.ini" #include <string.h> #ifdef WIN32 #include <Windows.h> #include

  • python读取xml文件方法解析

    关于python读取xml文章很多,但大多文章都是贴一个xml文件,然后再贴个处理文件的代码.这样并不利于初学者的学习,希望这篇文章可以更通俗易懂的教如何使用python来读取xml文件. 什么是xml? xml即可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. abc.xml <?xml version="1.0" encoding="utf-8"?> <catalog> <maxid

  • node.js生成与读取csv文件方法详解

    nodejs使用object-to-CSV库生成csv文件 object-to-CSV是一个非常棒的库,可以使用nodejs将对象数组快速写入CSV文件. 当然,还有许多其他的库.只是俺发现这对于俺的一个项目非常有用,因为俺必须生成一个一次性的CSV文件,所以俺编写了这个小教程. 在更面向性能的应用程序中,使用基于流的库(如fast-csv)可能适合您的需要. npm install objects-to-csv 引入库: const ObjectsToCsv = require('object

  • Delphi建立、读取、存贮INI文件的方法《一》

    一.有必要了解INI文件的结构: ;注释 [小节名] 关键字=值 ... INI文件允许有多个小节,每个小节又允许有多个关键字, "="后面是该关键字的值. 值的类型有三种:字符串.整型数值和布尔值.其中字符串存贮在INI文件中时没有引号,布尔真值用1表示,布尔假值用0表示. 注释以分号";"开头. 二.定义 1.在Interface的Uses节增加IniFiles: 2.在Var变量定义部分增加一行: myinifile:Tinifile; 然后,就可以对变量my

  • Qt读写ini文件的方法详解(含源码+注释)

    目录 一.示例Ini文件内容 二.Ini文件的写入 三.Ini文件的读取 3.1 第一种读取方式 3.2 第二种读取方式 3.3 读取结果示例 补充:获取所有节点和key以及节点的遍历 相关文章 总结 一.示例Ini文件内容 下方为本文所使用的ini文件的内容 [group1] key1=val1 key2=val2 sameKay=sameVal [group2] jian1=zhi1 jian2=zhi2 sameKay=sameZhi 二.Ini文件的写入 ini文件不需要像xml和jso

  • C#读写INI文件的方法

    本文实例讲述了C#读写INI文件的方法.分享给大家供大家参考.具体如下: 虽然微软早已经建议在WINDOWS中用注册表代替INI文件,但是在实际应用中,INI文件仍然有用武之地,尤其现在绿色软件的流行,越来越多的程序将自己的一些配置信息保存到了INI文件中. INI文件是文本文件,由若干节(section)组成,在每个带括号的标题下面,是若干个关键词(key)及其对应的值(Value) [Section] Key=Value VC中提供了API函数进行INI文件的读写操作,但是微软推出的C#编程

随机推荐