【问题标题】:linux shell append variable parameters to commandlinux shell 将变量参数附加到命令
【发布时间】:2017-08-02 07:56:34
【问题描述】:

我正在尝试获取一个 bash 脚本,该脚本可以为给定的参数生成 JSDoc,例如

./jsdoc.sh file.js another.js maybe-a-third.js

我陷入了如何将未知数量的参数传递给下一个 shell 命令的问题。

(另外,不知道如何检查参数是否存在,只有在不存在时才存在if [ -z ... ]

此代码最多可用于两个参数,但显然不是正确的方法...

#!/bin/bash

# would like to know how to do positive check
if [ -z "$1" ]
then echo no param
else
        d=$PWD
        cd ~/projects/jsdoc-toolkit/

        # this bit is obviously not the right approach
        if [ -z "$2" ]
        then java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $d/$1
        else java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $d/$1 $d/$2
        fi

        cp -R out/jsdoc $d
fi

任何其他关于我如何实现这一点的指针将不胜感激。

编辑:根据@skjaidev 的回答更新脚本 - 快乐的日子;)

#!/bin/bash

d=$PWD

for i in $*; do
    params=" $params $d/$i"
done

if [ -n "$1" ]; then
        cd ~/projects/jsdoc-toolkit/
        java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $params
        cp -R out/jsdoc $d
fi

【问题讨论】:

  • 使用 "$@" 代替 '$*` 以确保安全。我也会使用if (( $# > 0 ))——“$#”是参数的数量。

标签: linux bash shell jsdoc


【解决方案1】:

$* 包含所有参数。你可以遍历它们

for i in $*;
do
    params=" $params $d/$i"
done
your_cmd $params

【讨论】:

  • 在这种情况下,请始终使用 "$@" 而不是 $* -- 前者将保留包含空格的参数,后者将受到 shell 分词。
  • 即使"$@" 将在其扩展中保留空格,$i 的后续扩展将撤消效果,当 $params 在最后一行扩展时,仍然会产生带有嵌入空格的文件名在多个参数中,其中一个是预期的。特定于 Bash 的解决方案是使用 @glennjackman 提出的数组
  • 这将适用于包含空格的参数
【解决方案2】:

要处理包含空格的参数,请使用"$@" 进行迭代,并将其存储在数组中以供以后使用。

#!/bin/bash
if (( $# == 0 )); then
  echo "usage: $0 file ..."
  exit
fi
dir=$(pwd)
declare -a params
for file in "$@"; do params+=( "$dir/$file" ); done
cd ~/projects/jsdoc-toolkit/
java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ "${params[@]}"
cp -R out/jsdoc "$dir"

【讨论】:

    【解决方案3】:

    -n-z 的倒数,"$@" 是将所有参数传递给子命令的规范方式。这个和更多可以通过man bash找到。

    【讨论】:

    • 太好了 - 几乎解决了。最后一件事是我如何在每个参数前面加上$d/,以模仿$d/$1 $d/$2,但使用$@
    【解决方案4】:

    可以通过谨慎使用IFS 变量和特殊的$@ 参数来避免Bash 特定的功能(在本例中为数组)。

    #!/bin/sh
    
    dir=$(pwd)
    
    NEW_ARGV=""
    # carefully modify original arguments individually and separate them with newlines
    # in a new variable (in case they contain spaces)
    NEW_ARGV=""
    for var in "${@}"
    do
        NEW_ARGV="${NEW_ARGV}
    ${dir}/${var}"
    done
    
    SV_IFS=${IFS}
    # temporarily set IFS to a newline as per NEW_ARGV setup
    IFS="
    "
    # reset $@ with the modified newline-separated arguments
    set -- ${NEW_ARGV}
    IFS=${SV_IFS}
    
    # for testing, demonstrate each param is preserved
    c=0
    for i in "${@}"
    do
        c=`expr ${c} + 1`
        echo "args-via-var #${c}: \"${i}\""
    done
    
    cd ~/projects/jsdoc-toolkit/
    java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ "${@}"
    cp -R out/jsdoc "${dir}"
    

    没有必要重置$@,但这样做可以避免在多个地方弄乱IFS。无需经过$@ 就必须在任何扩展$NEW_ARGV 的地方设置IFS

    关注细节的人会注意到,当参数包含换行符时,此方法不会保留参数。可以使用任何控制字符代替换行符,当然 NUL 除外,也许 ASCII FS(文件分隔符,又名 ctrl-\)既有意义又不太可能发生使用有效的文件名。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-09
      相关资源
      最近更新 更多