题
我正在与公用事业合作(一致, ,但这不是要接受类似参数的重点:
$ 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中起作用,我很确定有一种更好的引用参数的方法。
解决方案
未经检查,它可能很简单:
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数组变量可能也是可行的 - 将参数累积到数组中,然后将数组作为参数传递给 unison
命令。
其他提示
如果您使用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[@]}"
在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
如果您想要一个特定于bash的版本,可以尝试
#! /bin/sh eval eval exec \ unison -path\\ \\\"{$(eval echo \\\"\\\${1..$#}\\\" | sed 's/ /,/g')}\\\"
如果您删除了所有三折叠引用的字符,这将变得更容易理解,但是我不会通过解释它来破坏乐趣:-)
主要的并发症是处理带有空格的文件名。这说明了三重引用和双重评估。
这是您可以令人满意地引用角色的方式:
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
不隶属于 StackOverflow