dim*_*ech 5 bash shell-script regular-expression
我已经看过几个 bash ini 解析脚本,并且我已经看到这个脚本在这里使用了几次,所以我想看看它是否适合我。看起来它会多次逐行读取 ini 文件,并且每次传递都会逐步构造一个最终被评估的函数。它适用于某些特殊字符,但不适用于其他字符。如果文件中的值包含单引号或大于/小于符号,则脚本返回语法错误。其他符号也会产生意想不到的结果。遇到这些字符时我该如何处理?
这是解析ini的函数。
#!/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 be =
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
}
Run Code Online (Sandbox Code Playgroud)
ini文件
[Section1]
value1=abc`def # unexpected EOF while looking for matching ``'
value2=ghi>jkl # syntax error near unexpected token `>'
value3=mno$pqr # executes ok but outputs "mnoqr"
value4=stu;vwx # executes ok but outputs "stu"
Run Code Online (Sandbox Code Playgroud)
您可以在 中做某事这一事实bash并不意味着您应该这样做。
sh(bash等)脚本最适合作为相对简单的包装器来启动程序或围绕文本处理命令。对于更复杂的任务,包括解析 ini 文件并对其进行操作,其他语言更合适。perl您是否考虑过用or编写脚本python?Config::INI两者都有很好的 .ini 文件解析器 -当我需要解析 ini 文件时,我曾多次使用过 perl 的模块。
但如果您坚持在 bash 中执行此操作,则应该使用关联数组而不是设置单个变量。
从这样的事情开始:
#! /bin/bash
inifile='user1074170.ini'
# declare $config to be an associative array
declare -A config
while IFS='=' read -r key val ; do
config["$key"]="$val"
done < <(sed -E -e '/^\[/d
s/#.*//
s/[[:blank:]]+$|^[[:blank:]]+//g' "$inifile" )
# now print out the config array
set | grep '^config='
Run Code Online (Sandbox Code Playgroud)
该sed脚本删除该[Section1]行(实际上,所有以左方括号开头的行[- 您将需要在具有多个部分的 ini 文件中以不同方式处理此问题[1]),并删除注释以及前导和尾随空格。该while循环读取每一行,用作=字段分隔符,并将内容分配给变量 $key 和 $val,然后将其添加到 $config 数组中。
输出:
config=([value1]="abc\`def" [value3]="mno\$pqr" [value2]="ghi>jkl" [value4]="stu;vwx" )
Run Code Online (Sandbox Code Playgroud)
您可以稍后在脚本中使用数组条目,如下所示:
$ echo value1 is "${config[value1]}"
value1 is abc`def
$ [ "${config[value4]}" = 'stu;vwx' ] && echo true
true
Run Code Online (Sandbox Code Playgroud)
[1]awk或者perl有以“段落”模式方便地阅读文件的简单方法。段落被定义为由一个或多个空行与其他文本块分隔开的文本块。
例如,要仅使用[Section1],请在将脚本输入到上面的循环awk之前插入下面的脚本:sedwhile
awk -v RS= -v ORS='\n\n' '/\[Section1\]/' "$inifile" | sed ...
Run Code Online (Sandbox Code Playgroud)
"$inifile"(当然,并从命令行末尾删除sed- 在您费尽心思从中提取文件之后,您不想再次输入[Section1]该文件)。
如果您只从 ini 文件中提取一个部分,则设置ORS并不是绝对必要的 - 但如果您要提取两个或多个部分,则对于保持段落分隔很有用。