Contents

Linux脚本解析属性文件

1. 概述

属性文件包含点分隔字符串形式的属性名称。

这种结构很好地捕捉了属性的层次结构。但是,在 bash 脚本中直接使用这些名称是很困难的。

在本教程中,我们将通过尽可能少地更改其名称结构来访问此类属性。

2. 问题陈述

让我们检查一个简单的属性文件test.properties

# test.properties
db.test.user=test user
db.test.passwd=password

作为第一次尝试,让我们将属性名称转换为 bash 变量。为此,我们只*source *属性文件:

#!/bin/bash
source test.properties
echo "User Id (db.test.user) = " $db.test.user
echo "user password (db.test.passwd) =" $db.test.passwd

不幸的是,我们最终会遇到错误:

test.properties: line 2: db.test.user=test user: command not found
test.properties: line 3: db.test.passwd=password: command not found
User Id (db.test.user) =  .test.user
user password (db.test.passwd) = .test.passwd

这种方法失败了,因为点是 bash 变量名称中的非法字符。

3. 从属性名称中映射出点

让我们把点变成一些合法的字符。

bash 变量的名称只能包含数字、字母和下划线。因此我们需要选择下划线’_’:

#!/bin/sh
file="./test.properties"
while IFS='=' read -r key value
do
    key=$(echo $key | tr '.' '_')
    eval ${key}=\${value}
done < "$file"
echo "User Id (db.test.user) =         " ${db_test_user}
echo "user password (db.test.passwd) = " ${db_test_passwd}

我们分别*read * key和value,用等号作为分隔符。接下来,tr 将属性名称中的点转换为下划线。最后,eval 定义了一个具有新名称的 bash 变量。

现在让我们检查这个脚本产生的结果:

User Id (db.test.user) =          test user
user password (db.test.passwd) =  password

在这种方法中,我们创建了一堆 bash 变量,每个属性一个。随后,我们使用映射名称来引用属性。

4. 使用数组作为查找表

从 Bash 4.0 开始,我们可以从关联数组 中受益。因此,让我们使用属性的名称作为其值的键:

#!/bin/bash
# array declaration
declare -A props
file="./test.properties"
while IFS='=' read -r key value; do
   props["$key"]="$value"
done < "$file"
echo "User Id (db.test.user) =         " ${props["db.test.user"]}
echo "user password (db.test.passwd) = " ${props["db.test.passwd"]}

key的形式没有限制。因此,我们可以使用自己的名称访问属性。

5. 使用包装函数从文件中提取变量

让我们创建一个在属性文件中搜索属性名称的函数。结果,它返回属性的值。

在后台,我们将使用grep 命令并随后从找到的行中cut 属性值:

#!/bin/bash
file="./test.properties"
function prop {
    grep "${1}" ${file} | cut -d'=' -f2
}
echo "User Id (db.test.user) =         " $(prop 'db.test.user')
echo "user password (db.test.passwd) = " $(prop 'db.test.passwd')

我们使用其原始名称来引用该属性。但是,每次选择变量都需要再次对整个文件进行 grep。因此,对于大型属性文件,此方法可能会很慢。