我正在使用一个实用程序(unison,但这不是重点)接受如下参数:
$ unison -path path1 -path path2 -path path3
我想写一个我可以这样运行的脚本:
$ myscript path1 path2 path3
我希望有一个符合Posix标准的解决方案,但特定于bash也会很好。
我猜它应该是这样的:
#!/bin/sh
unison ${*/ / -path }
但这不起作用。
编辑:好的,我想我得到了一些东西:
#!/bin/bash
PARAMS=
for arg in "$@"
do
PARAMS+=" -path '$arg'"
done
unison $PARAMS
问题是这只适用于bash,我很确定有更好的方法引用参数。
答案 0 :(得分: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
命令的参数传递。
答案 1 :(得分: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[@]}"
答案 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
答案 3 :(得分:1)
如果您需要特定于bash的特定版本,可以尝试
#! /bin/sh eval eval exec \ unison -path\\ \\\"{$(eval echo \\\"\\\${1..$#}\\\" | sed 's/ /,/g')}\\\"
如果删除所有三反斜杠引用的字符,这将变得更容易理解,但我不会通过解释它来破坏乐趣: - )
主要的复杂功能是处理带空格的文件名。这说明了三重反弹报价和双重评估。
答案 4 :(得分:1)
以下是您如何令人满意地引用您的角色:
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