我正在与公用事业合作(一致, ,但这不是要接受类似参数的重点:

$ 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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top