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

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

问题描述

我遇到了在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实现实现了不同的子集(请参见下面的shlexxargs之间的增量).
  • 很难以编程方式生成. 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 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\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")

这篇关于从字符串中正确读取带引号/转义的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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