在sh中操纵参数

时间:2009-06-08 14:41:52

标签: bash shell scripting sh

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

5 个答案:

答案 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