繁体   English   中英

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

[英]Passing command line parameters in bash, detecting content of parameters

我正在写一个bash脚本

  1. 根据传递的第一个参数,行为有所不同(到目前为止没有问题)
  2. 将其余的参数传递给命令(到目前为止没有问题)
  3. 如果参数包含字符串,则行为会有所不同

看起来像:

[[ "${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

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

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

我想要它运行

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

代替。 有小费吗?

首先,如果要将*传递给脚本,则必须防止命令行中的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语句。 试试看,如果您有任何问题,请告诉我。

您提到了命令行:

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

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

目前尚不清楚是否仅在*跟随-a选项时才需要替换* ,或者是否应该在任何自变量中替换*。 我将假定所有参数都需要替换; 如果仅应替换-a之后的参数,则差别不大。

如果没有处理whatever/*的代码,则命令如下所示:

[[ "${1}" = "emerge" ]] && exec emerge -uDN "${@:2}" || exit 1

区别:

  1. exec是可选的,但保证在执行emerge命令之后什么都不会执行(除非找不到emerge命令,在这种情况下, || exit 1确保没有其他执行)。

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

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

数组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会扩展元字符(确切地说是* ),而不是依靠shell来扩展。 正如问题所假设的那样,它还假设eix生成的名称中没有空格。 如果有的话, $(…)表示法将在空格(或制表符或换行符,…)处拆分名称。

最好将这段代码作为then子句的主体进行处理

if [[ "${1}" = "emerge" ]]
then
    …
fi

这比尝试将所有代码都压缩到一行中(可以这样做,但这样做没有意义,很多人不这样做)要清楚得多。

这是一个线索:

#!/bin/sh

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

case "$x" in
*\**)
    echo "Yes"
    ;;
    *)
    echo "No"
    ;;
esac

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM