在不使用“source”的情况下读取BASH中的配置文件

时间:2010-12-14 00:24:15

标签: bash grep eval config

我正在尝试读取格式如下的配置文件:

USER = username
TARGET = arrows

我意识到如果我摆脱空间,我可以简单地获取配置文件,但出于安全考虑,我试图避免这种情况。我知道有一种方法可以逐行读取配置文件。我认为这个过程就像:

  1. 将行读入数组
  2. 过滤掉以#
  3. 开头的所有行
  4. 在数组
  5. 中搜索变量名称

    之后我迷路了。任何和所有的帮助将不胜感激。我尝试过这样的事情没有成功:

    backup2.config>cat ~/1
    
    grep '^[^#].*' | while read one two;do
        echo $two
    done
    

    我从我发现的论坛帖子中删除了它,因为我对shell脚本很新,所以不确定如何修改它以满足我的需求。

    http://www.linuxquestions.org/questions/programming-9/bash-shell-program-read-a-configuration-file-276852/


    是否可以通过循环遍历两个数组来自动分配变量?

    for (( i = 0 ; i < ${#VALUE[@]} ; i++ ))
    do
        "${NAME[i]}"=VALUE[i]           
    done
    echo $USER
    

    这样调用$ USER会输出“用户名”?上面的代码不起作用,但我知道解决方案与此类似。

4 个答案:

答案 0 :(得分:10)

以下脚本遍历输入文件中的每一行(在我的情况下为 vars ),并针对=进行模式匹配。如果找到等号,则会使用Parameter Expansion中解析变量 name 。然后它将每个部分分别存储在它自己的数组中, name value

#!/bin/bash

i=0
while read line; do
  if [[ "$line" =~ ^[^#]*= ]]; then
    name[i]=${line%% =*}
    value[i]=${line#*= }
    ((i++))
  fi
done < vars

echo "total array elements: ${#name[@]}"
echo "name[0]: ${name[0]}"
echo "value[0]: ${value[0]}"
echo "name[1]: ${name[1]}"
echo "value[1]: ${value[1]}"
echo "name array: ${name[@]}"
echo "value array: ${value[@]}"

输入

$ cat vars
sdf
USER = username
TARGET = arrows
asdf
as23

输出

$ ./varscript
total array elements: 2
name[0]: USER
value[0]: username
name[1]: TARGET
value[1]: arrows
name array: USER TARGET
value array: username arrows

答案 1 :(得分:5)

首先,USER是一个shell环境变量,所以如果你使用其他东西可能会更好。使用小写或混合大小写变量名是避免名称冲突的一种方法。

#!/bin/bash
configfile="/path/to/file"
shopt -s extglob
while IFS='= ' read lhs rhs
do
    if [[ $lhs != *( )#* ]]
    then
        # you can test for variables to accept or other conditions here
        declare $lhs=$rhs
    fi
done < "$configfile"

这会将文件中的变量设置为与之关联的值。

echo "Username: $USER, Target: $TARGET"

会输出

  

用户名:用户名,目标:箭头

使用键和值执行此操作的另一种方法是使用关联数组:

while循环之前添加此行:

declare -A settings

删除declare循环中的while行,并将其替换为:

    settings[$lhs]=$rhs

然后:

# set keys
user=USER
target=TARGET
# access values
echo "Username: ${settings[$user]}, Target: ${settings[$target]}"

会输出

  

用户名:用户名,目标:箭头

答案 2 :(得分:3)

我有一个只需要非常有限数量的设置的脚本,并且一次处理一个,所以我已经调整了SiegeX的答案,将我关心的设置列入白名单,并对它们采取行动。< / p>

我还删除了=周围空格的要求,转而使用the trim function from another answer忽略任何存在空格。

function trim()
{
    local var=$1;
    var="${var#"${var%%[![:space:]]*}"}";   # remove leading whitespace characters
    var="${var%"${var##*[![:space:]]}"}";   # remove trailing whitespace characters
    echo -n "$var";
}

while read line; do
    if [[ "$line" =~ ^[^#]*= ]]; then
        setting_name=$(trim "${line%%=*}");
        setting_value=$(trim "${line#*=}");

        case "$setting_name" in
            max_foos)
                prune_foos $setting_value;
            ;;
            max_bars)
                prune_bars $setting_value;
            ;;
            *)
                echo "Unrecognised setting: $setting_name";
            ;;
        esac;
    fi
done <"$config_file";

答案 3 :(得分:1)

感谢SiegeX。我认为您提到的后续更新并未反映在此网址中。

我必须编辑正则表达式以删除引号才能使其正常工作。使用引号,返回的数组为空。

i=0
while read line; do
  if [[ "$line" =~ ^[^#]*= ]]; then
    name[i]=${line%% =*}
    value[i]=${line##*= }
    ((i++))
  fi
 done < vars

更好的版本是。

i=0
while read line; do
if [[ "$line" =~ ^[^#]*= ]]; then
        name[i]=`echo $line | cut -d'=' -f 1`
            value[i]=`echo $line | cut -d'=' -f 2`
        ((i++))
fi
done < vars

如果配置文件中“=”之前和之后没有空格,则第一个版本会出现问题。此外,如果缺少值,我会看到名称和值填充相同。第二个版本没有这些。此外,它还会删除不需要的前导和尾随空格。

此版本读取的值可以在其中。早期版本首次出现时会分裂=。

i=0
while read line; do
if [[ "$line" =~ ^[^#]*= ]]; then
        name[i]=`echo $line | cut -d'=' -f 1`
            value[i]=`echo $line | cut -d'=' -f 2-`
        ((i++))
fi
done < vars