问题描述
我遇到了在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(因为我相信swap可以实现我希望它正确执行的功能),如何使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?
推荐答案
一些入门单词
如果可能的话,不要使用带引号的字符串作为输入格式.
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'
,它会生成一个带壳引号的字符串,其中包含任意变量的内容,但是在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\0' <<<"$ARGS")
swap "${array[@]}"
...将把$ARGS
的已解析内容放入数组array
.如果您想从文件中读取,请用<filename
代替<<<"$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\n' <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 + "\0")
'
}
while IFS= read -r -d ''; do
array+=( "$REPLY" )
done < <(shlex_split <<<"$ARGS")
这篇关于从字符串中正确读取带引号/转义的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!