bash 传递变量时正确使用 curl --data-urlencode

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25270560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:36:47  来源:igfitidea点击:

Properly using curl --data-urlencode when passing a variable

bashoptimizationcurlsed

提问by yab

I'm trying to optimize my code and one particular piece of code is borrowed. I'd like to remove the sed so I'm not using any external processes in my main loop.

我正在尝试优化我的代码并且借用了一段特定的代码。我想删除 sed,这样我就不会在主循环中使用任何外部进程。

function sendMsg () {
value=$(echo  | sed 's/ /%20/g;s/!/%21/g;s/"/%22/g;s/#/%23/g;s/\&/%26/g;s/'\''/%28/g;s/(/%28/g;s/)/%29/g;s/:/%3A/g;s/\//%2F/g');
str="http://www.xxxx.com/api.ashx?v=1&k=$Key&a=send&w=$value";
curl -s $str;
}

I've edited this for clarity. The $value is simply to convert to a proper url for output via the curl command at the end of the function.

为了清楚起见,我已经编辑了这个。$value 只是通过函数末尾的 curl 命令转换为正确的 url 以进行输出。

While this works just fine, I'm mostly interested in making this as fast to process as possible without forking to outside processes if I can.

虽然这工作得很好,但我最感兴趣的是尽可能快地处理它,如果可以的话,不分叉到外部进程。

Thanks for the comments so far!

感谢您到目前为止的评论!

Where I'm at so far is this:

到目前为止我在哪里是这样的:

function sendMsg () {
str="http://www.xxxx.com/api.ashx?v=1&k=$Key&a=send&w=";
curl -s $str --data-urlencode "";
}

Am I on the right track at least?

我至少在正确的轨道上吗?

采纳答案by David W.

First, the answer to your question: If you are doing a single substitution or filtering, using pattern matching is faster:

首先,回答您的问题:如果您正在进行单个替换或过滤,则使用模式匹配会更快:

$ foo=${bar/old/new}               # Faster
$ foo=$(sed 's/old/new/' <<<$bar   # Slower

The first doesn't require spawning a sub-shell, and running sed, then substituting this back into $foo. However, if you are doing this almost a dozen times, I believe using sedmay be faster:

第一个不需要产生一个子shell,并运行sed,然后将其替换回$foo. 但是,如果您这样做几乎十次,我相信使用sed可能会更快:

value=$(sed -e 's/ /%20/g' \
   -e 's/!/%21/g' \
   -e 's/"/%22/g' \
   -e 's/#/%23/g' \
   -e 's/\&/%26/g' \
   -e 's/'\''/%28/g' \
   -e 's/(/%28/g' \
   -e 's/)/%29/g' \
   -e 's/:/%3A/g' \
   -e 's/\//%2F/g'<<<);

Note that this syntax is easier to read since each substitution command is on its own line. Also note that <<<eliminates the need to echo and pipe.

请注意,此语法更易于阅读,因为每个替换命令都在其自己的行上。还要注意,这<<<消除了回声和管道的需要。

This only does a single call to sedwhile pattern matching has to be done multiple times.

这只调用一次,sed而必须多次进行模式匹配。

However, you should be using --dataand --data-uuencodeinstead of building the query string yourself:

但是,您应该使用--dataand--data-uuencode而不是自己构建查询字符串:

$ curl -s http://www.xxxx.com/api.ashx \
    --data v=1 \
    --data k=$Key \
    --data a=send \
    --data-urlencode w="$value";

The --data--urlencodewill encode the value of $valuefor you, so you don't have to do it. Unfortunately, this parameter doesn't exist in all versions of curl. It was added in version 7.18.0 back in January of 2008. Run curl --versionto see what version you have:

--data--urlencode将编码的价值$value给你,所以你不必这样做。不幸的是,并非所有版本的curl. 它于 2008 年 1 月在 7.18.0 版本中添加。运行curl --version以查看您拥有的版本:

$ curl --version     # Life is good
curl 7.30.0 (x86_64-apple-darwin13.0) libcurl/7.30.0 SecureTransport zlib/1.2.5

$ curl --version     # David Sad
curl 7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5


Addendum

附录

In attempting this I'm getting an 'unsupported API versionERROR', even though my curl --version reports 7.29.0

在尝试此操作时,我收到了“不受支持的 API 版本错误”,即使我的 curl --version 报告为 7.29.0

I can't test what you have, but I decided to try our Jenkins server to see if I can set the build description. I made sure the description has spaces in it, so it requires --data-urlencoding. This command worked:

我无法测试你所拥有的,但我决定尝试我们的 Jenkins 服务器,看看我是否可以设置构建描述。我确保描述中有空格,所以它需要--data-urlencoding. 此命令有效:

$ curl --user dweintraub:swordfish \
    --data Submit=Submit \
    --data-urlencode description="This is my test descripition" \
    http://jenkins.corpwad.com/jenkins/job/Admin-5.1.1/138/submitDescription

This is as if I did:

这就像我做了:

$ curl -user "dweintraub:swordfish http://jenkins.corpwad.com/jenkins/job/Admin-5.1.1/138/submitDescription?Submit=Submit&desciption=This%20is%20my%20test%20descripition"

Note that --dataadds the question mark for you.

请注意,--data为您添加了问号。

(No, swordfishisn't my password).

(不,swordfish不是我的密码)。

It's not as complex as your command, but it might help point out where you're having problems. Do you have a user name and password? If so, you need the --userparameter.

它不像您的命令那么复杂,但它可能有助于指出您的问题所在。你有用户名和密码吗?如果是这样,您需要该--user参数。

回答by chepner

If you have to do this a lot, the overhead of spawning multiple sedprocesses might add up. In that case, you can use the following lines instead:

如果您必须经常这样做,则产生多个sed进程的开销可能会增加。在这种情况下,您可以使用以下几行:

value=${1// /%20/}
value=${value//!/%21}
value=${value//\"/%22}
value=${value//\#/%23}
value=${value//&/%26}
value=${value//\'/%27}
value=${value//(/%28}
value=${value//)/%29}
value=${value//:/%3A}
value=${value//\//%2F}