【问题标题】:manipulate parameters in sh在 sh 中操作参数
【发布时间】:2010-11-01 04:50:25
【问题描述】:

我正在使用一个接受以下参数的实用程序(unison,但这不是重点):

$ unison -path path1 -path path2 -path path3

我想编写一个可以这样运行的 sh 脚本:

$ myscript path1 path2 path3

我希望有一个符合 Posix 的解决方案,但特定于 bash 的解决方案也很好。

我猜应该是这样的:

#!/bin/sh
unison ${*/ / -path }

但这不起作用。

编辑:好的,我想我明白了:

#!/bin/bash
PARAMS=
for arg in "$@"
do
    PARAMS+=" -path '$arg'"
done
unison $PARAMS

问题是这只适用于 bash,我很确定有更好的方法来引用参数。

【问题讨论】:

  • 您是否希望有一个不涉及for 循环的单行解决方案?
  • 引入单引号可能是个坏主意。正如所写的,unison 命令可以看到引号,这不是您想要的。如果参数中没有任何单引号,则可以使用单引号保护参数的外部 - 但您可能需要一个 eval 才能使其正常工作。
  • mywiki.wooledge.org/BashFAQ/050 在这里很有趣——尽管并非所有答案都适用于 POSIX sh,但它对您提出的解决方案存在哪些问题的解释是完全相关的。

标签: bash shell scripting sh


【解决方案1】:

不勾选,可以这么简单:

exec unison -path $1 -path $2 -path $3

如果您不在路径名中嵌入空格,则可以使用以下方法处理可变数量的参数:

arglist=""
for path in "$@"
do
    arglist="$arglist -path $path"
done
exec unison $arglist

如果路径名中有空格,则必须更加努力;我通常使用一个名为escape 的自定义程序,它引用需要引用的参数,以及eval

arglist=""
for path in "$@"
do
    path=$(escape "$path")
    arglist="$arglist -path $path"
done
eval exec unison "$arglist"

我注意到使用 Perl 或 Python 会更容易处理带有空格的参数 - 但问题是关于 shell。

在 Bash 中使用 shell 数组变量也可能是可行的 - 将参数构建到一个数组中并将该数组作为参数传递给 unison 命令。

【讨论】:

    【解决方案2】:

    如果您使用 Bash 的数组,所有引用问题都会消失。

    #!/bin/bash
    args=()
    for i in "$@"; do
        # With Bash >= 3:
        args+=(-path "$i")
        # +=() doesn't work in Bash 2
        # args=("${args[@]}" -path "$i")
    done
    exec unison "${args[@]}"
    

    【讨论】:

    • 同上@Gordon,感谢您提供有关 Bash 2 兼容性的信息!
    【解决方案3】:

    在 Bash 中,您可以使用"${@/#/-path }",它将每个位置参数的开头替换为“-path”。要表示字符串的结尾,请使用% 而不是#

    这是一个使用sed 和重复-e 选项的简单演示脚本。 (当然还有更高效的方法来使用sed。)

    #!/bin/bash
    echo "Resulting arguments: ${@/#/-e }"
    sed "${@/#/-e }"
    

    并像这样运行它:

    $ echo abc | demo s/a/A/ s/b/B/
    

    我们得到:

    Resulting arguments: -e s/a/A/ -e s/b/B/
    ABc
    

    【讨论】:

      【解决方案4】:

      如果你想要一个重度 bash 特定的版本,你可以试试

      #! /bin/sh 评估评估执行\ unison -path\\ \\\"{$(eval echo \\\"\\\${1..$#}\\\" | sed 's/ /,/g')}\\\"

      如果您删除所有用三重反斜杠引用的字符,这将变得更容易理解,但我不会通过解释来破坏乐趣:-)

      主要的复杂性是处理带有空格的文件名。这就是三重反冲引用和双重评估的原因。

      【讨论】:

      • WTF?如果您要专门针对 bash,正确的做法是使用数组——这样您就可以从简单、易读的代码中受益,该代码可以清楚地写出显然没有错误,而不是需要依靠没有明显的错误。
      • 那个答案是奇怪的、神秘的和幽默的,而不是“正确的事情”的例子。
      【解决方案5】:

      您可以通过以下方式令人满意地引用您的角色:

      job_strategy()
      {
        local p
        for p in "$@"; do
          printf '-path\000%s\000' "$p"
        done
      }
      
      job_process()
      {
        xargs -0 unison
      }
      
      job_strategy "path1" "path2" "path3" | job_process
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2022-01-04
      • 2020-08-11
      • 2013-06-07
      • 1970-01-01
      • 2021-11-02
      • 2016-06-22
      相关资源
      最近更新 更多