Bash 在sh中操作参数
我正在使用一个实用程序(,但这不是重点),它接受如下参数:Bash 在sh中操作参数,bash,shell,scripting,sh,Bash,Shell,Scripting,Sh,我正在使用一个实用程序(,但这不是重点),它接受如下参数: $ unison -path path1 -path path2 -path path3 我想写一个sh脚本,我可以这样运行: $ myscript path1 path2 path3 $ echo abc | demo s/a/A/ s/b/B/ 我希望有一个兼容Posix的解决方案,但是特定于bash的解决方案也不错 我猜应该是这样的: #!/bin/sh unison ${*/ / -path } 但这不起作用 编辑:好的
$ unison -path path1 -path path2 -path path3
我想写一个sh脚本,我可以这样运行:
$ myscript path1 path2 path3
$ echo abc | demo s/a/A/ s/b/B/
我希望有一个兼容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的
在Bash中使用shell数组变量也可能是可行的—将参数构建到一个数组中,并将数组作为参数传递给
unison
命令。如果您想要一个高度特定于Bash的版本,可以尝试
#! /bin/sh
eval eval exec \
unison -path\\ \\\"{$(eval echo \\\"\\\${1..$#}\\\" | sed 's/ /,/g')}\\\"
#! /垃圾箱/垃圾箱
eval eval exec\
unison-path\\\\\“{$(eval echo\\\”\\\\${1..$\\\\\\\\\“\124; sed's//,/g')}\\”
如果删除所有带三个反斜杠引号的字符,这将更容易理解,但我不会因为解释它而破坏乐趣:-)
主要的复杂性是处理带有空格的文件名。这就解释了三重反冲报价和双重求值。如果使用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
)
然后像这样运行它:
$ myscript path1 path2 path3
$ echo abc | demo s/a/A/ s/b/B/
我们得到:
Resulting arguments: -e s/a/A/ -e s/b/B/
ABc
以下是如何令人满意地引用您的角色:
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
您是否希望一个不涉及
for
循环的单行解决方案?引入单引号可能是个坏主意。正如所写的那样,unison命令可以看到引号,这不是您想要的。如果参数中没有任何单引号,则使用单引号保护参数的外部是可以的,但是您可能需要一个eval才能使其正常工作。这里很有意思——尽管不是所有的答案都适用于POSIX sh,但它对您提出的解决方案中存在的问题的解释是完全相关的。同上@Gordon,另外感谢您包含关于Bash 2兼容性的内容!世界跆拳道联盟?如果你想成为bash特定的人,正确的做法是使用数组——这样你就可以得到一个简单易读的代码,可以清楚地写出来明显没有bug,而不是依赖于没有明显的bug。这个答案是奇怪的、神秘的和幽默的,不是“正确的事情”的例子。也就是说,xargs-0
POSIX?我的印象是它是一个GNU扩展。它没有在Uppps中列出,我错误地引用了FreeBSD手册页面:它应该是POSIX.2
。