bash脚本函数参数问题

bash脚本函数参数问题

不知道为什么会产生错误。这是模拟我真实代码的测试代码。我想编写一个包装器find并希望允许任何参数,因此我将每个参数用单引号括起来。

#!/bin/bash

function find2 {

   ARGS="/usr/bin/find"
   while [[ $# -gt 0 ]]; do
      ARGS="$ARGS '$1'"
      shift
   done
   echo CALLING:  $ARGS
   $ARGS

}

find2 /tmp/test -name "hello.c"    # THIS IS THE DESIRED IMPLEMENTATION (doesn't work)

find '/tmp/test' '-name' 'hello.c'     # THIS IS FOR DEBUGGING (works)

我想“find2”工作,但它不起作用。我得到以下输出:

CALLING: /usr/bin/find '/tmp/test' '-name' 'hello.c'
/usr/bin/find: `\'/tmp/test\'': No such file or directory
/usr/bin/find: `\'-name\'': No such file or directory
/usr/bin/find: `\'hello.c\'': No such file or directory

但是,如果我直接使用完全相同的命令(由 find2 生成),它可以正常工作:

/tmp/test/hello.c

不知道发生了什么事。

答案1

(在 Bash 中)您可以更改为值数组:

find2() {

    ARGS="/usr/bin/find"
    ARGS+=( "$@" )
    echo CALLING:  "${ARGS[@]}"
    "${ARGS[@]}"

}

find2 /tmp/test -name "hello.c"

但这有效并且相当简单:

find2() {
    ARGS=( "/usr/bin/find" "$@" )
    echo CALLING:  "${ARGS[@]}"
    "${ARGS[@]}"
}

find2 /tmp/test -name "hello.c"

当然,直接方式也可以(在任何带有函数的 shell 中):

find2() {    /usr/bin/find "$@";   }

find2 /tmp/test -name "hello.c"

为什么原来的代码失败了?

要“查看”代码在做什么,您可以使用 set -x 或更好的方法,将 echo 替换为 printf,如下所示:

find2() {

    ARGS="/usr/bin/find"
    ARGS+=( "$@" )
    printf '<%s> ' CALLING:  "${ARGS[@]}"; echo
    "${ARGS[@]}"

}

find2 /tmp/test -name "hello.c"

当你执行它时,你会看到:

$ ./script.sh
<CALLING:> </usr/bin/find> </tmp/test> <-name> <hello.c> 

每个参数都是一个单独的元素(注意 <> 的位置)。

但是,在您的原始代码中(添加 printf):

function find2 {

    ARGS="/usr/bin/find"
    while [[ $# -gt 0 ]]; do
        ARGS="$ARGS '$1'"
        shift
    done
    printf '<%s> ' CALLING:  "${ARGS[@]}"; echo
    $ARGS

}   

find2 /tmp/test -name "hello.c"

执行时你将得到:

$ ./script.sh
<CALLING:> </usr/bin/find '/tmp/test' '-name' 'hello.c'>

所有值都是一个长文本行,而不是单独的参数(请注意 <> 的位置)。

答案2

如果您将该行更改ARGS="$ARGS '$1'"ARGS="$ARGS $1"(删除单引号),它应该可以工作。

相关内容