从字符串中正确读取引用/转义参数 [英] Reading quoted/escaped arguments correctly from a string

查看:27
本文介绍了从字符串中正确读取引用/转义参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在向 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 实现实现不同的子集(请参阅下面的 shlexxargs 之间的增量).
  • 很难以编程方式生成.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 and xargs 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆