Shell是否回显完整内容而没有转义符

时间:2019-01-18 01:43:00

标签: linux bash shell

我的shell脚本如下:

#!/bin/bash
account0=0xf2de2e86b9b634f655e441a4e8353c9bf59352d7
passwd=123456
data={"jsonrpc":"2.0","method":"personal_unlockAccount","id":1,"params":[$account0,$passwd]}
echo $data

我的期望是(“注意”):

{"jsonrpc":"2.0","method":"personal_unlockAccount","id":1,"params":[0xf2de2e86b9b634f655e441a4e8353c9bf59352d7,123456]}

不是

{jsonrpc:2.0,method:personal_unlockAccount,id:1,params:[0xf2de2e86b9b634f655e441a4e8353c9bf59352d7,123456]}

: 我不想不想使用转义符,怎么办? 内容插入xml标签“ <![CDATA[..."..]]>

1 个答案:

答案 0 :(得分:5)

echo不是您的问题。 (这是一个 a 问题,但不是您的立即问题)。

您的问题是引号根本没有分配给变量。引号是语法;它读取它们作为有关如何解析字符串的说明的一部分。因此,它们被bash本身消耗,除非被引用或转义,否则它们不会被分配为值。


要使整件事字面意思,可以将整行用单引号引起来:

data='{"jsonrpc":"2.0","method":"personal_unlockAccount","id":1,"params":[$account0,$passwd]}'
echo "$data"

...或者您可以使用Heredoc生成它,但要付出一定的效率:

{ IFS= read -r -d '' data || [[ $data ]]; } <<'EOF'
{"jsonrpc":"2.0","method":"personal_unlockAccount","id":1,"params":[$account0,$passwd]}
EOF
echo "$data"

假设您要执行扩展,将account0替换为名称相同的shell变量,那么错误的方法是从单引号上下文切换到在引用变量之前用双引号引起来的上下文:

# BAD: Does not guarantee result is valid JSON
account0=exampleName; passwd=examplePassword
data='{"jsonrpc":"2.0","method":"personal_unlockAccount","id":1,"params":["'"$account0"'","'"$passwd"'"]}'
echo "$data"

...或切换到未引用的Heredoc(使用<<EOF,而不是<<'EOF'):

# BAD: Does not guarantee result is valid JSON
account0=exampleName; passwd=examplePassword
{ IFS= read -r -d '' data || [[ $data ]]; } <<EOF
{"jsonrpc":"2.0","method":"personal_unlockAccount","id":1,"params":["$account0","$passwd"]}
EOF
echo "$data"

正确的实现方法是使用jq生成包含文字值的安全转义JSON:

# GOOD: Result will always be syntactically valid JSON.
account0=exampleName; passwd=examplePassword
data=$(jq -cn --arg account0 "$account0" --arg passwd "$passwd" '
  {"jsonrpc":"2.0","method":"personal_unlockAccount","id":1,"params":[$account0,$passwd]}
')
echo "$data"

还记得我说过echo的问题所在,即使这不是您的直接问题吗?请参阅its POSIX specification的APPLICATION USAGE部分,以了解为什么在处理任意数据时它本来就不可靠,请记住,bash可以在运行时配置为根据该规范中描述的任何变体运行。使用printf '%s\n' "$foo"而不是echo "$foo"来获得一致和可靠的行为。