从字符串中正确读取引用/转义参数 [英] Reading quoted/escaped arguments correctly from a string
问题描述
我在向 Bash 脚本中的命令传递参数时遇到问题.
I'm encountering an issue passing an argument to a command in a Bash script.
poc.sh:
#!/bin/bash
ARGS='"hi there" test'
./swap ${ARGS}
交换:
#!/bin/sh
echo "${2}" "${1}"
当前输出为:
there" "hi
仅更改 poc.sh(因为我相信交换可以正确执行我想要的操作),如何让 poc.sh 传递hi there"并作为两个参数进行测试,hi there"周围没有引号它吗?
Changing only poc.sh (as I believe swap does what I want it to correctly), how do I get poc.sh to pass "hi there" and test as two arguments, with "hi there" having no quotes around it?
推荐答案
一些介绍性词
如果可能,不要使用 shell 引用的字符串作为输入格式.
A Few Introductory Words
If at all possible, don't use shell-quoted strings as an input format.
- 很难一致地解析:不同的 shell 有不同的扩展,不同的非 shell 实现实现不同的子集(请参阅下面的
shlex
和xargs
之间的增量). - 很难以编程方式生成.ksh 和 bash 有
printf '%q'
,它将生成一个包含任意变量内容的 shell 引用字符串,但在 POSIX sh 标准中不存在与此等效的字符串. - 很容易解析糟糕.许多使用这种格式的人都使用
eval
,这具有很大的安全问题.
- It's hard to parse consistently: Different shells have different extensions, and different non-shell implementations implement different subsets (see the deltas between
shlex
andxargs
below). - It's hard to programmatically generate. ksh and bash have
printf '%q'
, which will generate a shell-quoted string with contents of an arbitrary variable, but no equivalent exists to this in the POSIX sh standard. - It's easy to parse badly. Many folks consuming this format use
eval
, which has substantial security concerns.
NUL 分隔的流是一种更好的做法,因为它们可以准确地表示任何可能的 shell 数组或参数列表,而不会产生任何歧义.
NUL-delimited streams are a far better practice, as they can accurately represent any possible shell array or argument list with no ambiguity whatsoever.
如果您使用 shell 引用从人工生成的输入源中获取参数列表,您可以考虑使用 xargs
来解析它.考虑:
If you're getting your argument list from a human-generated input source using shell quoting, you might consider using xargs
to parse it. Consider:
array=( )
while IFS= read -r -d ''; do
array+=( "$REPLY" )
done < <(xargs printf '%s ' <<<"$ARGS")
swap "${array[@]}"
...将解析后的$ARGS
内容放入数组array
.如果您想从文件中读取,请将 <<<"$ARGS"
.
...will put the parsed content of $ARGS
into the array array
. If you wanted to read from a file instead, substitute <filename
for <<<"$ARGS"
.
如果您尝试编写符合 POSIX sh 的代码,这将变得更加棘手.(为了降低复杂性,我将在这里假设文件输入):
If you're trying to write code compliant with POSIX sh, this gets trickier. (I'm going to assume file input here for reduced complexity):
# 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
' <argfile | run_with_args ./swap
<小时>
这些方法比运行 xargs ./swap <argfile
更安全,因为如果有更多或更长的参数,它会抛出错误,而不是将多余的参数作为单独的命令运行.
These approaches are safer than running xargs ./swap <argfile
inasmuch as it will throw an error if there are more or longer arguments than can be accommodated, rather than running excess arguments as separate commands.
如果您需要比 xargs
实现的更准确的 POSIX sh 解析,请考虑改用 Python shlex
模块:
If you need more accurate POSIX sh parsing than xargs
implements, consider using the Python shlex
module instead:
shlex_split() {
python -c '
import shlex, sys
for item in shlex.split(sys.stdin.read()):
sys.stdout.write(item + " ")
'
}
while IFS= read -r -d ''; do
array+=( "$REPLY" )
done < <(shlex_split <<<"$ARGS")
这篇关于从字符串中正确读取引用/转义参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!