将命令行参数分成两个列表并传递给程序 (shell)
Separate command-line arguments into two lists and pass to programs (shell)
我想要做的是获取类似命令的参数列表,如 abc "def ghi" "foo bar" baz
(请注意,一些参数被引用是因为它们包含空格),并将它们分成两个参数列表,然后得到传递给脚本调用的其他程序。例如,一个程序的奇数参数和另一个程序的偶数参数。保持正确的引用很重要。
请注意,我需要一个纯 Bourne Shell 脚本的解决方案(即 sh
而不是 bash
等)。我在 Bash 中这样做的方法是使用数组,但 Bourne Shell 当然不支持数组。
这可能是您所需要的。 las,它使用eval。 YMMV.
#!/bin/sh
# Samples
foo() { showme foo "$@"; }
bar() { showme bar "$@"; }
showme() {
echo " args:"
shift
local c=0
while [ $# -gt 0 ]; do
printf '\t%-3d %s\n' $((c=c+1)) ""
shift
done
}
while [ $# -gt 0 ]; do
foo="$foo \"\""
bar="$bar \"\""
shift 2
done
eval foo $foo
eval bar $bar
这里没有魔法——我们只是将带有引号装甲的交替参数编码到变量中,这样当您 eval
该行时它们就会被正确处理。
我用基于 ash 的 FreeBSD /bin/sh 测试了这个。 shell 接近于 POSIX.1 但不一定是 "Bourne"。如果您的 shell 不接受 shift
的参数,您可以在 while 循环中简单地移动两次。类似地,showme()
函数递增一个计数器,如果我的方法不适合您,可以通过您喜欢的任何方式实现该操作。我相信其他一切都很标准。
以对原始参数进行两次迭代为代价,您可以定义一个函数,该函数可以 运行 仅使用偶数或奇数参数的 简单 命令。这允许我们将函数的参数用作附加数组。
# 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=
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 '%s\n' "$@"
}
# Example of using run_it
run_it cmd even "$@"
run_it cmd odd "$@"
我想要做的是获取类似命令的参数列表,如 abc "def ghi" "foo bar" baz
(请注意,一些参数被引用是因为它们包含空格),并将它们分成两个参数列表,然后得到传递给脚本调用的其他程序。例如,一个程序的奇数参数和另一个程序的偶数参数。保持正确的引用很重要。
请注意,我需要一个纯 Bourne Shell 脚本的解决方案(即 sh
而不是 bash
等)。我在 Bash 中这样做的方法是使用数组,但 Bourne Shell 当然不支持数组。
这可能是您所需要的。 las,它使用eval。 YMMV.
#!/bin/sh
# Samples
foo() { showme foo "$@"; }
bar() { showme bar "$@"; }
showme() {
echo " args:"
shift
local c=0
while [ $# -gt 0 ]; do
printf '\t%-3d %s\n' $((c=c+1)) ""
shift
done
}
while [ $# -gt 0 ]; do
foo="$foo \"\""
bar="$bar \"\""
shift 2
done
eval foo $foo
eval bar $bar
这里没有魔法——我们只是将带有引号装甲的交替参数编码到变量中,这样当您 eval
该行时它们就会被正确处理。
我用基于 ash 的 FreeBSD /bin/sh 测试了这个。 shell 接近于 POSIX.1 但不一定是 "Bourne"。如果您的 shell 不接受 shift
的参数,您可以在 while 循环中简单地移动两次。类似地,showme()
函数递增一个计数器,如果我的方法不适合您,可以通过您喜欢的任何方式实现该操作。我相信其他一切都很标准。
以对原始参数进行两次迭代为代价,您可以定义一个函数,该函数可以 运行 仅使用偶数或奇数参数的 简单 命令。这允许我们将函数的参数用作附加数组。
# 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=
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 '%s\n' "$@"
}
# Example of using run_it
run_it cmd even "$@"
run_it cmd odd "$@"