一些介绍性的话
如果可能,不要使用 shell 引用的字符串作为输入格式。
- 很难进行一致的解析:不同的 shell 有不同的扩展,不同的非 shell 实现实现不同的子集(请参阅下面的
shlex 和 xargs 之间的增量)。
- 很难以编程方式生成。 ksh 和 bash 有
printf '%q',它将生成一个带有任意变量内容的 shell 引用字符串,但在 POSIX sh 标准中不存在与此等效的字符串。
- 很容易解析糟糕。许多使用这种格式的人都使用
eval,这有很大的安全问题。
NUL 分隔的流是一种更好的做法,因为它们可以准确地表示 任何 可能的 shell 数组或参数列表,没有任何歧义。
xargs,带有 bashisms
如果您使用 shell 引用从人工生成的输入源获取参数列表,您可以考虑使用 xargs 来解析它。考虑:
array=( )
while IFS= read -r -d ''; do
array+=( "$REPLY" )
done < <(xargs printf '%s\0' <<<"$ARGS")
swap "${array[@]}"
...将$ARGS解析后的内容放入数组array。如果您想改为从文件中读取,请将 <filename 替换为 <<<"$ARGS"。
xargs,POSIX 兼容
如果您尝试编写与 POSIX sh 兼容的代码,这将变得更加棘手。 (为了降低复杂性,我将在此处假设文件输入):
# This does not work with entries containing literal newlines; you need bash for that.
run_with_args() {
while IFS= read -r entry; do
set -- "$@" "$entry"
done
"$@"
}
xargs printf '%s\n' <argfile | run_with_args ./swap
这些方法比运行 xargs ./swap <argfile 更安全,因为如果有更多或更长的参数超出了可以容纳的范围,它会抛出错误,而不是将多余的参数作为单独的命令运行。
Python shlex -- 而不是 xargs -- 带有 bashisms
如果您需要比 xargs 实现更准确的 POSIX sh 解析,请考虑改用 Python shlex 模块:
shlex_split() {
python -c '
import shlex, sys
for item in shlex.split(sys.stdin.read()):
sys.stdout.write(item + "\0")
'
}
while IFS= read -r -d ''; do
array+=( "$REPLY" )
done < <(shlex_split <<<"$ARGS")