【问题标题】:parse arguments with multiple multi words in bash在bash中解析具有多个多字的参数
【发布时间】:2018-10-07 08:21:04
【问题描述】:

请在下面找到简化的 bash 脚本 parseArg.sh :-

#!/usr/bin/env bash

function parse(){

    local propsFile=$1


    echo "search file is : >$propsFile<"

    while IFS='=' read -r packageKey packageValue;
    do


        echo "package value is >$packageValue<"

        packageProcessor $packageValue

        echo "---------------------------------------------------------"
    done < "$propsFile"
}

function packageProcessor(){
    echo "Total args : $#"
    echo "All args value : >$@<"
    for arg in "$@"
    do
        echo "$arg"
    done
}

$@

下面是同一目录下的配置文件repos.conf :-

cm5-centos6.6="https://archive.cloudera.com/cm5/redhat/6/x86_64/cm/5/ cm5-centos6.6 cm5/centos6.6 cm5/centos6.6 cm5-centos_6_6 "Cdh 5 for CentOS 6.6""

当我在同一目录中执行以下命令时:-

sh parseArg.sh 解析 repos.conf

我期待 6 个参数,但它总共提供了 10 个参数。 以下是实际输出:-

search file is : >repos.conf<
package value is >"https://archive.cloudera.com/cm5/redhat/6/x86_64/cm/5/ cm5-centos6.6 cm5/centos6.6 cm5/centos6.6 cm5-centos_6_6 "Cdh 5 for CentOS 6.6""<
Total args : 10
All args value : >"https://archive.cloudera.com/cm5/redhat/6/x86_64/cm/5/ cm5-centos6.6 cm5/centos6.6 cm5/centos6.6 cm5-centos_6_6 "Cdh 5 for CentOS 6.6""<
"https://archive.cloudera.com/cm5/redhat/6/x86_64/cm/5/
cm5-centos6.6
cm5/centos6.6
cm5/centos6.6
cm5-centos_6_6
"Cdh
5
for
CentOS
6.6""
---------------------------------------------------------

【问题讨论】:

  • 请看:shellcheck.net
  • 哎呀,您需要找到更强大的配置文件格式。也许是 JSON 或 YAML。
  • @glennjackman :不确定,在 bash 中解析 yaml 或 json 有多容易。所以想到使用这种格式的配置文件。
  • 您还需要验证脚本的命令行参数:sh parseArg.sh rm -rf . 实际上会灾难性地执行该rm 命令:为“未知子命令:rm”抛出错误

标签: bash parsing arguments


【解决方案1】:

parse 函数中,变量packageValue 将包含一个字符串,其值为:

"https://archive.cloudera.com/cm5/redhat/6/x86_64/cm/5/ cm5-centos6.6 cm5/centos6.6 cm5/centos6.6 cm5-centos_6_6 "Cdh 5 for CentOS 6.6""

前导和尾随引号出现在变量的值中。该字符串中的引号是纯字符。

将其解析为 6 个独立组件的唯一可行方法是使用 eval 强制 shell 尊重“内部”引号。首先,您必须去掉前导引号和尾引号:

    tmp=${packageValue#\"}
    packageValue=${tmp%\"}
    packageProcessor "$packageValue"

然后,在packageProcessor 函数中,您将不得不使用eval 将字符串分配为数组,但您需要暂时禁用文件名生成:您想利用分词,但不受影响通过路径扩展。

set -f
eval "elements=($1)"
set +f

现在可以

declare -p elements
for arg in "${elements[@]}"; do echo "$arg"; done

说了这么多,还是别做了。这本质上是不安全的。使用不会将您暴露在不安全的 eval 调用中的数据存储格式,只是为了拆分您的数据。

如果您可以完全控制该配置文件的内容,请使用 shell 语法使其成为您可以获取的脚本:

declare -a cm5_centos_6_6=(https://archive.cloudera.com/cm5/redhat/6/x86_64/cm/5/ cm5-centos6.6 cm5/centos6.6 cm5/centos6.6 cm5-centos_6_6 "Cdh 5 for CentOS 6.6")

【讨论】:

  • command "declare -p elements" 发出输出 declare -a elements='([0]="archive.cloudera.com/cm5/redhat/6/x86_64/cm/5" [1]="cm5-centos6.6" [2]="cm5 /centos6.6" [3]="cm5/centos6.6" [4]="cm5-centos_6_6" [5]="CentOS 6.6 的 Cdh 5")'。有什么办法可以禁用它。
  • 删除该行。我添加它是为了调试并展示成功。
  • 你没有听从“不要这样做”的建议,是吗?
  • 根据业务需求,我们只有三个选择来存储配置(json、xml 或普通配置文件)。我不确定,在 bash 中解析 json 或 xml 有多复杂。所以,我们决定使用普通的配置文件。截至目前,我对python不太擅长。可能稍后,当我们包含 python 时,我们会将配置从普通配置移动到 xml。
猜你喜欢
  • 2012-04-17
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多