传递命令行参数,参数

问题描述:

我在写这将传递命令行参数,参数

  1. 行为不同基于传递的第一个参数一个bash脚本检测内容(没有概率到目前为止)
  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 

但是,如果认为 “无所谓” 是包含*一个字符串,如

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

我想让它运行

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

改为。有小费吗?

+0

这是不可能的,因为Bash甚至在它传递到脚本之前展开'*'。除非你在引号中用''whatever/*“'写出 – user123444555621 2014-09-05 01:18:51

+0

这是可能的,你只需引用你的输入。即'myscript emerge -uDN -a'whatever/*'whatever2 --option'或者变成一团糟。 – 2014-09-05 05:19:50

这里有一个线索:

#!/bin/sh 

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

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

你提到的命令行:

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

的唯一途径myscript会看到它的参数列表中的*是如果没有子目录whatever下的电流目录,或者它是一个空目录(严格来说:如果它包含任何文件,名称全部以.开头),并且无论哪种情况,您都没有设置shopt -s nullglob。如果这些条件不满足,调用myscript的shell将相应地替换*(in),并且myscript将不会看到*。 (当然,如果你引用的论据 - "whatever/*"'whatever/*',然后myscript也会看到*元字符,不论nullglobwhatever子目录的存在或不存在。)

目前尚不清楚是否*需求只有在遵循-a选项时才被替换,或者在任何论点中都应该被替换。我会假设所有的论点都需要被取代;如果它只是应该替换的-a之后的参数,那么它并没有很大的不同。

如果没有代码来处理whatever/*,命令看起来像:

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

差异:

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

  2. 使用"[email protected]"来保存呈现给脚本的参数。没有双引号,[email protected]$*之间没有区别。在双引号内,"$*"会生成单个字符串,但"[email protected]"会生成传递给脚本的每个参数。 "${@: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将扩展元字符(*要准确),而不是依靠外壳这样做。正如问题所假设的那样,它还假设eix生成的名称中没有空格。如果有的话,$(…)表示法将在空格(或制表符或换行符...)处拆分名称。

该代码会得到更好的为then条款的身体

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

处理这将是比试图挤压所有的代码成一条线(其可以做的更清晰,但没有指出这样做,许多人指出不这样做)。

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

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

既然你已经在使用[[操作,注:以下是庆典只有的解决方案,并不能移植到SH。如果要判断$ 3包含*你可以使用=~操作:

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

您也可以重写,如果逻辑变得有点凄惨的复合命令到嵌套if-else语句。试试看,如果您有任何问题,请告诉我。