在bash中传递命令行参数,检测参数的内容

时间:2014-09-05 01:09:49

标签: bash parameter-passing

我正在写一个

的bash脚本
  1. 基于传递的第一个参数(目前没有概率)
  2. 表现不同
  3. 将其余参数传递给命令(目前没有问题)
  4. 如果参数包含字符串,则
  5. 表现不同

    看起来像:

    [[ "${1}" = "-h" || "${1}" = "--help" ]] && echo -e "somehelp"
    [[ "${1}" = "echo" ]] && echo ${*:2}
    [[ "${1}" = "emerge" ]] && emerge -uDN ${*:2}
    some-magic-here
    

    现在,如果我这样做

    myscript emerge -a whatever whatever2 --option 
    

    它会运行

    emerge -uDN -a whatever whatever2 --option
    

    但是,如果“what”是包含*的字符串,例如

    myscript emerge -uDN -a whatever/* whatever2 --option
    

    我希望它能够运行

    emerge -uDN -a $(eix -u --only-names whatever/*) whatever2 --option
    

    代替。有什么提示吗?

3 个答案:

答案 0 :(得分:1)

首先,如果要将*传递给脚本,则必须阻止shell在命令行上进行扩展。最简单的方法是引用它:

myscript emerge -a 'whatever/*' whatever2 --option

由于您已经在使用[[运算符,注意:以下是仅限bash 解决方案,而且无法移植到sh。要确定$ 3是否包含*,您可以使用=~运算符:

[[ "${1}" == "emerge" ]] && {
    [[ "$3" =~ "*" ]] && \
        emerge -uDN $2 $(eix -u --only-names $3) ${*:4} || \
        emerge -uDN ${*:2}
}

如果逻辑变得有点模糊,你也可以将复合命令重写为嵌套的if-else语句。试一试,如果您有任何问题,请告诉我。

答案 1 :(得分:0)

您提到了命令行:

myscript emerge -uDN -a whatever/* whatever2 --option

myscript在其参数列表中看到*的唯一方法是当前目录下没有子目录whatever,或者它是一个空目录(严格地说:如果它包含所有文件,名称均以.开头),在任何一种情况下,您都没有shopt -s nullglob设置。如果不满足这些条件,则调用myscript的shell将适当地替换*(in),myscript将无法看到*。 (当然,如果您引用参数 - "whatever/*"'whatever/*',那么myscript也会看到*元字符,无论nullglob是否存在或是没有whatever子目录。)

目前尚不清楚*是否只有在-a选项之后才需要替换,或者是否应该在任何参数中替换-a。我将假设所有论点都需要被替换;如果它只是应该被替换的whatever/*之后的参数,那就没有什么不同了。

如果没有代码来处理[[ "${1}" = "emerge" ]] && exec emerge -uDN "${@:2}" || exit 1 ,命令看起来像:

exec

的差异:

  1. emerge是可选的,但保证在执行emerge命令后不会执行任何操作(除非找不到|| exit 1命令,在这种情况下"$@"确保不会执行任何其他操作。)

  2. 使用$@保留呈现给脚本的参数。如果没有双引号,$*"$*"之间没有区别。在双引号内,"$@"生成单个字符串,但"${@:2}"生成传递给脚本的每个参数。 *符号表示第二个到最后一个参数。

  3. 要处理任何参数的*,我们需要检测arglist。如果我们使用数组,这将是最简单的。

    数组emerge将包含要传递给*命令的参数。我们需要迭代脚本的参数,检查arglist=( "-uDN" ) for arg in "${@:2}" do case "$arg" in (*\**) arglist+=( $(eix -u --only-names "$arg") );; (*) arglist+=( "$arg" );; esac done exec emerge "${arglist[@]}" exit 1

    的外观
    eix

    请注意,这假设*将扩展元字符(eix以确切),而不是依赖shell来执行此操作。正如问题所假设的那样,它还假设$(…)生成的名称中没有空格。如果有,then表示法将在空格(或制表符或换行符,......)处拆分名称。

    此代码最好作为

    if [[ "${1}" = "emerge" ]] then … fi 子句的主体处理
    {{1}}

    这比尝试将所有代码压缩到一行更清楚(这可以做到,但没有必要这样做,很多人指出不这样做)。

答案 2 :(得分:-1)

这里有一条线索:

#!/bin/sh

x="bbbccc"     # Put different strings in here, and see what happens

case "$x" in
*\**)
    echo "Yes"
    ;;
    *)
    echo "No"
    ;;
esac
相关问题