将命令行参数分成两个列表并传递给程序 (shell)



我想做的是获取一个类似命令的参数列表,如abc "def ghi" "foo bar" baz(请注意,有些参数被引用是因为它们包含空格(,并将它们分成两个参数列表,然后传递给脚本调用的其他程序。例如,一个程序的奇数编号参数和另一个程序的偶数编号参数。保留适当的引用很重要。

请注意,我需要纯 Bourne Shell 脚本的解决方案(即,sh不是bash之类的(。我在 Bash 中这样做的方法是使用数组,但当然 Bourne Shell 不支持数组。

以迭代原始参数两次为代价,您可以定义一个函数,该函数可以仅使用偶数或奇数参数运行简单命令。这允许我们将函数的参数用作附加数组。

# Usage:
#  run_it <cmd> [even|odd] ...
# 
#  Runs <cmd> using only the even or odd arguments, as specified.
run_it () {
cmd=${1:?Missing command name}
parity=${2:?Missing parity}
shift 2
n=$#
# Collect the odd arguments by discarding the first
# one, turning the odd arguments into the even arguments.
if [ $# -ge 1 ] && [ $parity = odd ]; then
shift
n=$((n - 1))
fi
# Repeatedly move the first argument to the
# to the end of the list and discard the second argument.
# Keep going until you have moved or discarded each argument.
while [ "$n" -gt 0 ]; do
x=$1
if [ $n -ge 2 ]; then
shift 2
else
shift
fi
set -- "$@" "$x"
n=$((n-2))
done
# Run the given command with the arguments that are left.
"$cmd" "$@"
}
# Example command
cmd () {
printf '%sn' "$@"
}
# Example of using run_it
run_it cmd even "$@"
run_it cmd odd "$@"

这可能是你需要的。唉,它使用eval。扬子晚报.

#!/bin/sh
# Samples
foo() { showme foo "$@"; }
bar() { showme bar "$@"; }
showme() {
echo "$1 args:"
shift
local c=0
while [ $# -gt 0 ]; do
printf 't%-3d %sn' $((c=c+1)) "$1"
shift
done
}
while [ $# -gt 0 ]; do
foo="$foo "$1""
bar="$bar "$2""
shift 2
done
eval foo $foo
eval bar $bar

这里没有魔法 - 我们只是将带有引号装甲的交替参数编码为变量,以便在您eval行时正确处理它们。

我用 FreeBSD 的/bin/sh 测试了这一点,它基于 ash。外壳接近POSIX.1,但不一定是"Bourne"。如果你的 shell 不接受要shift的参数,你可以在 while 循环中简单地移动两次。同样,showme()函数会增加一个计数器,如果我的动作不适合你,可以用你最喜欢的任何方式实现。我相信其他一切都很标准。

最新更新