如何解决Awk调用Curl时含双引号变量的Shell语法错误?
问题
我在Bash脚本中编写了如下代码:
<mycommand> | awk ' ... $1 == "array" { test = 1 } END { if (test) run() } function run() { print "Messages:", _msg cmd="curl -s \""URL"\" -F \"param1="_param1"\" -F \"message="_msg"\" > /dev/null " system(cmd); fflush() } '
当run()函数执行时,会打印信息并通过system调用curl命令。但_msg变量是包含多个双引号的字符串,输出示例为:
"Messages:": "text1", "text2", "text3"
传递给curl时触发错误:sh: 1: Syntax error: Unterminated quoted string。请问如何正确传入cmd变量?需转义双引号吗?该如何操作?
解决方案
核心问题是_msg里的双引号会破坏shell命令的引号结构,必须对这些双引号进行转义,或者换一种更安全的参数传递方式:
方法1:转义_msg中的双引号
在构造cmd之前,先用awk的gsub函数把_msg里的双引号替换成shell能识别的转义格式\":
function run() { print "Messages:", _msg # 转义_msg中的双引号 escaped_msg = _msg gsub(/"/, "\\\"", escaped_msg) cmd="curl -s \""URL"\" -F \"param1="_param1"\" -F \"message="escaped_msg"\" > /dev/null " system(cmd); fflush() }
这里gsub(/"/, "\\\"", escaped_msg)的逻辑是:awk里要表示一个反斜杠需要写两个,所以最终输出给shell的是\",能让shell把_msg里的双引号当作普通字符处理。
方法2:用curl的--data-urlencode自动处理特殊字符
如果接口支持application/x-www-form-urlencoded格式(而非必须multipart/form-data),可以用--data-urlencode参数,它会自动对参数里的特殊字符(包括双引号)做URL编码,无需手动转义:
function run() { print "Messages:", _msg cmd="curl -s \""URL"\" -d \"param1="_param1"\" --data-urlencode \"message="_msg"\" > /dev/null " system(cmd); fflush() }
方法3:改用单引号包裹curl参数
把curl的参数用单引号包裹,shell会将单引号内的内容视为纯字符串,不会解析里面的双引号。注意awk里单引号需要用字符串拼接的方式处理:
function run() { print "Messages:", _msg cmd="curl -s '"URL"' -F 'param1="_param1"' -F 'message=" _msg "' > /dev/null " system(cmd); fflush() }
注意:如果_param1或_msg里包含单引号,这个方法会失效,此时优先用方法1。
内容的提问来源于stack exchange,提问作者Frank
相关产品推荐
相关产品推荐

