【问题标题】:Moving code into a bash function causes misfunction将代码移动到 bash 函数中会导致功能错误
【发布时间】:2018-06-11 16:10:19
【问题描述】:

我正在编写一个 bash 脚本,该脚本应该读取配置文件并稍后使用。 配置文件如下所示:

[config]
key1=value1
key2=value2
key3=value3

在弄清楚如何解析文件时,我发现这个问题很有帮助:Bash Parse Arrays From Config File

答案中的相关代码是这样的:

while read line; do 
if [[ $line =~ ^"["(.+)"]"$ ]]; then 
    arrname=${BASH_REMATCH[1]}
    declare -A $arrname
elif [[ $line =~ ^([_[:alpha:]][_[:alnum:]]*)"="(.*) ]]; then 
    declare ${arrname}[${BASH_REMATCH[1]}]="${BASH_REMATCH[2]}"
fi
done < config.conf

当我将它用作纯脚本时,此代码效果很好。但是,如果我用函数包装它,脚本会在读取第一个键后终止(我使用 set -o xtrace 来找出它)。

为什么是这个代码:

read_config() {
    while read line; do 
    if [[ $line =~ ^"["(.+)"]"$ ]]; then 
        arrname=${BASH_REMATCH[1]}
        declare -A $arrname
    elif [[ $line =~ ^([_[:alpha:]][_[:alnum:]]*)"="(.*) ]]; then 
        declare ${arrname}[${BASH_REMATCH[1]}]="${BASH_REMATCH[2]}"
    fi
  done < $1
}
read_config config.conf

输出如下所示:

++ read_config
++ read line
++ [[ [config] =~ ^\[(.+)]$ ]]
++ arrname=config
++ declare -A config
++ read line
++ [[ local=127.0.0.1 =~ ^\[(.+)]$ ]]
++ [[ local=127.0.0.1 =~ ^([_[:alpha:]][_[:alnum:]]*)=(.*) ]]
++ declare 'config[local]=127.0.0.1'
Segmentation fault (core dumped)

导致错误(命令终止),而第一个纯脚本不是吗?

(标题远非完美,我不知道如何更准确地描述它。)

谢谢!

【问题讨论】:

  • 这两种情况都可以正常工作,似乎无法重现您的错误。你安装了什么bash 版本?您可以发布看到的完整错误吗?
  • 我编辑了错误的问题,版本是:GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
  • 一定是个很老的 Bash。 4.4.12 不以declare 'config[local]=127.0.0.1' 为核心。
  • 在我的机器上,在“纯”版本中它没有,在函数 id 中。我不知道有什么区别。
  • 可能是 Bash 错误。

标签: bash


【解决方案1】:

正如 Inian 所说,两个版本都运行时没有语法错误。但是第二个有一个逻辑错误,因为 Bash 手册页说:

在函数中使用时,声明和排版使每个名称都成为本地名称,就像使用本地命令一样,除非提供了 -g 选项

这意味着,您的配置数据仅在您的函数中可用。当函数终止时,配置会被垃圾回收。

【讨论】:

  • 我什至没有进入尝试访问配置对象的阶段 - 脚本在读取第一个键值对后终止
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-08
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多