4

我正在使用一个接受以下参数的实用程序(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,我很确定有更好的方法来引用参数。

4

5 回答 5

5

未经检查,它可能很简单:

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命令。

于 2009-06-08T14:53:36.853 回答
4

如果你使用 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[@]}"
于 2009-06-09T17:51:28.257 回答
3

在 Bash 中,您可以使用"${@/#/-path }"which 将每个位置参数的开头替换为“-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
于 2009-11-05T18:19:59.000 回答
1

Here is how you can satisfyingly quote your characters:

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
于 2014-09-12T20:01:26.007 回答
1

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

#!/bin/sh

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

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

主要的复杂性是处理带有空格的文件名。这解释了三重反弹引用和双重评估。

于 2009-06-08T15:41:59.283 回答