这里参考了下面这篇博客
https://blog.csdn.net/liubeck/article/details/7497156
不过按照上面的代码好像有点问题,后来搞了半天实现了需求。
配置文件为myconfig.ini
[Class]
ids=student1,student2,student3
files=profilefile
[student1]
name=LiLei
age=16
[student2]
name=HanMeiMei
age=15
[student3]
name=Lucy
age=15
如何取[student1]下面name的值呢?用下面这行代码:
awk -F '=' '/\[student1\]/{a=1}a==1&&$1~/name/{print $2;exit}' myconfig.ini
这句指令涉及到的内容挺多的,查了半天才搞明白,详细解释一下:
首先这句指令用了awk命令,awk命令通常是将所列出的行,根据条件打印出某一列或几列,想多了解的话可以参考下网上资料
https://www.cnblogs.com/ftl1012/p/9250541.html
“-F” 是awk命令的一个选项,用来指定后面记录(行)的分隔符号,就是确定用什么作为分隔符号把记录分成一个一个的域,这里后面跟的 ‘=’ 表示用等号来分隔。
再往后单引号中间是awk命令,awk命令由模式和动作组成,模式是一组用来测试输入行是否需要执行动作的规则,动作是包含语句、函数和表达式的执行过程,简单来说就是模式决定动作何时触发和触发事件,动作执行对输入行的处理。
/ \ [student1 \ ]/ 这就是上面说的awk命令的模式,模式与动作之间用 / 来分开,表示匹配到这个模式的话执行后面的动作,这里要匹配的是 [strudent1] ,因为方括号[ ] 在shell中有特殊的意义,使用转义符号\ 表示单纯的 [ ] 符号,所以这里就是[strudent1] 。
{a=1} 花括号里面的内容是awk命令的动作,这里就是给a赋值为1.
a==1&&$1~/name/ 这里又是一个模式匹配,先是判断a是否等于1(因为刚才已经给a赋值为1,所以这里肯定相等),还要$1~/name/,$1表示第一域,就是字符串用分隔符号分割后的第一段, ~ 符号在awk命令中是关系运算符号,表示匹配正则表达式,这里就是要第一域为name
{print $2;exit} 这里又是一个动作,打印第二域,即第一域name的取值,然后退出awk命令。
myconfig.ini 当然表示对 myconfig.ini 文件的操作。
这句话整体的含义就是: 对 myconfig.ini 文件进行操作,用=对每一行进行分割,找到匹配[student1]的section,再从 [student1] 下面找到name这一opiton,最后打印option的取值。
有了这句话,现在就可以使用shell脚本对 myconfig.ini 文件进行操作了:
configOperate.sh
#!/bin/bash
getconfig()
{
Section=$1 #传递的第一个参数
ConFile=$2 #传递的第二个参数
Options="name\tage\t"
echo $Options|tr '\\t' '\t'
for loop in $(echo $Options|tr '\\t' ' ') #tr替换命令
do
#{gsub(/[[:blank:]]*/,"",$2)去除值两边的空格内容
awk -F '=' '/\['"$Section"'\]/{a=1}a==1&&$1~/'"$loop"'/{gsub(/[[:blank:]]*/,"",$2);printf("%s\t\t",$2) ;exit}' $ConFile
done
}
#更改变量名称
CONFIGFILE=$1
#文件名称
echo -e "ConfigName:$CONFIGFILE \n"
#取得ids中的每个id把,号分隔改成空格,因为循环内容要以空格分隔开来
profile=`sed -n '/ids/'p $CONFIGFILE | awk -F= '{print $2}' | sed 's/,/ /g'`
#对于一个配置文件中的所有id循环
for stdudent in $profile
do
echo "--------------------------------------------------"
echo "student:$stdudent"
getconfig $stdudent $CONFIGFILE
echo -e "\n"
done
脚本的解释:
首先定义了getconfig()函数,用来将选定的section中的每个option以及取值打印出来。其中的$1、$2是调用函数时传递给它的第一个和第二个参数。
下面两句
Options="name\tage\t"
echo $Options|tr '\\t' '\t'
这两句是为了打印两个option :name和age
tr '\\t' '\t'
tr命令用于替换,这里是将 \t 这两个普通符号替换成了制表符号tab,注意\t的用法,因为\符号除了是一个普通符号之外还表示转义字符,所以用转义字符 \ 将它本身转化视作一个普通的符号。
这两句的结果是输出
name age
下面一句
for loop in $(echo $Options|tr '\\t' ' ')
这句的意思就是循环中让loop分别取name和age
也可以这样写
for loop in name age
但是不能用
for loop in `echo $Options|tr '\\t' ' '` # ` 执行符号
虽然在这句话中能实现的作用一样,但是放到整个脚本中却会有问题,不清楚为什么。
有了之前的解释,这一句
awk -F '=' '/\['"$Section"'\]/{a=1}a==1&&$1~/'"$loop"'/{gsub(/[[:blank:]]*/,"",$2);printf("%s\t\t",$2) ;exit}' $ConFile
就好理解了,不同之除就是如果用变量来代替student1…的话,格式是 ‘"$Section"’,先双引号,再单引号,gsub(/[[:blank:]]*/,"",$2) 去除值两边的空格内容,printf 是格式化输出。
以上是定义的getconfig函数。
下面需要解释的是
profile=`sed -n '/ids/'p $CONFIGFILE | awk -F= '{print $2}' | sed 's/,/ /g'`
执行符号` 表示将里面命令运行的结果赋值给变量
sed -n '/ids/'p $CONFIGFILE
是sed命令的一种用法,表示读取文件中匹配ids的行,具体可以参考
https://www.cnblogs.com/ctaixw/p/5860221.html
awk -F= '{print $2}'
用=将这一行分割,打印第二部分,即 student1,student2,student3
sed 's/,/ /g'
将逗号替换为空格
下面的内容相对简单, 主要是函数的调用方法为
getconfig $stdudent $CONFIGFILE
最后的运行结果:
mk90@mk90-e420:~/Documents/myshell$ ./configOperate.sh myconfig.ini ConfigName:myconfig.ini
--------------------------------------------------
student:student1
name age
LiLei 16
--------------------------------------------------
student:student2
name age
HanMeiMei 15
--------------------------------------------------
student:student3
name age
Lucy 15