echo 输出的内容中包括调用的变量时为何会自动乱序?内详

2023-02-28 01:52:16 +08:00
 mylovesaber

本意是希望下载 github 文件的时候先检查下有没有达到拉取频率上限,并打印出提示信息,但输出的提示信息是乱序的,具体命令如下一行一条命令:

githubGetRateInfo=$(curl -s -I -X POST https://api.github.com/users/octocat)
postLimit=$(echo "${githubGetRateInfo}"|awk /^X-RateLimit-Limit/'{print $2}')
postRemaining=$(echo "${githubGetRateInfo}"|awk /^X-RateLimit-Remaining/'{print $2}')
echo "GitHub 调用速率为 ${postLimit} 次 /小时"

echo 输出结果预期效果:

GitHub 调用速率为 60 次 /小时

实际输出:

 次 /小时 用速率为 60

以下是 curl 那条命令获取的信息,目的是筛选出X-RateLimit-LimitX-RateLimit-Remaining的值

HTTP/1.1 404 Not Found
Server: GitHub.com
Date: Mon, 27 Feb 2023 17:37:26 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 84
X-GitHub-Media-Type: github.v3; format=json
x-github-api-version-selected: 2022-11-28
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1677522152
X-RateLimit-Used: 3
X-RateLimit-Resource: core
Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
Vary: Accept-Encoding, Accept, X-Requested-With
X-GitHub-Request-Id: xxxxxxxxxxx

有没有大佬知道这是什么原因导致的顺序错乱?是我疏忽了什么地方吗?

2434 次点击
所在节点    Linux
36 条回复
mylovesaber
2023-02-28 17:47:21 +08:00
@aloxaf 7.81.0 和 7.29.0 都存在,前者服务器 ubuntu minimal22.04 ,后者应该是 centos7 ,
mylovesaber
2023-02-28 17:48:08 +08:00
@hahahahahahahah 两个方式都尝试了,最开始脚本中出现意外输出,手动 echo 也出现了
mylovesaber
2023-02-28 17:55:50 +08:00
@geelaw 是我理解的太无脑让大家见笑了,之前的确没遇到过这问题,第一次遇到给整懵了,网上查也没头绪,没想到是编码的问题
mylovesaber
2023-02-28 17:57:58 +08:00
@julyclyde 哈哈,其实你也理解错我意思了,我是有点调侃甩锅的意思,但我基于假设 curl 远端显示什么就应该原封不动得打印给我的默认想法的,而不是让 curl 对输出的结果做解析后再反馈给我
mylovesaber
2023-02-28 18:00:09 +08:00
关于本贴问题我昨天加班到凌晨刚准备走,最后一次测试居然发现有这个问题就两头都发了请教,那边给到了我提示,然后我把我的处理方法也补充进去了,v2 没法在回复中用 md ,也没法编辑超时的帖子,所以直接贴隔壁站的链接吧。

https://stackoverflow.com/questions/75584213/if-the-text-output-by-linux-echo-contains-variables-the-text-will-be-out-of-ord
AoEiuV020CN
2023-02-28 18:06:58 +08:00
@mylovesaber #20 这个接口不会占用次数的,变了说明有其他人在用你一样的 ip ,你没有唯一的公网 ip 吧,
建议带上 token 再调用 api ,就和 ip 无关了,

下载地址的话就是 browser_download_url ,

诶你既然要解析下载地址,那不还是要提前拉一个 jq 或者其他什么解析 json 的,rate limit 不就可以一样的办法解析处理, 还是没必要读 header 呀,

官方 header 用途是你实际调用后判断是否还有剩次数,而不是在实际使用之前特地去拿 header 的,
mylovesaber
2023-02-28 18:42:44 +08:00
@AoEiuV020CN 我是为了应对不同数据库的备份要求,写了个 shell 的工具,然后读取配置文件来实现获取信息,读的是 yml ,所以解析工具就需要拉一个 yq ,还对应加了一个可以检测 yq 是否有升级的模块,然后测试下载、校验等操作的代码是否工作正常的时候意外遇到了 github 有解析上限的问题,所以不得以才加了个 25 楼的模块用于检查上限的问题,再为了不占用次数的话引入个 jq 感觉是不是有点多此一举哈哈,我想了解的 key 不是那个,是你发的那个链接里面有五段,每段都有各自的 rate limit 和 remaining 信息,我不知道如果是获取 release 文件链接的话应该会占用哪个 rate limit 和 remaining 信息

---

获取下载链接的话这两行就够了:
```shell
remoteYQLatestHTML="$(curl -s --max-time 15 v 站不能用外链 repos/mikefarah/yq/releases/latest)"
yqDownloadLink=$(echo "${remoteYQLatestHTML}" | grep "browser_download_url.*.yq_linux_amd64\"" | awk -F '[" ]' '{print $(NF-1)}')
```
AoEiuV020CN
2023-02-28 18:58:46 +08:00
@mylovesaber #27
.rate.remaining 就是对应你 header 里的值,

另外你也可以直接把链接替换成我那个,然后照样读取 header ,就不消耗次数也不用改代码了,
AoEiuV020CN
2023-02-28 19:03:13 +08:00
@mylovesaber #27 顺便我也遇到过同样问题,
我最后是选择打印 http code ,api 失败就报错不继续,
顺便加上了 token ,有 token 一小时免费一千次,没有 token 一个 ip 一小时免费只有 60 次,太小气了,
AoEiuV020CN
2023-02-28 19:06:39 +08:00
@mylovesaber #27 你这样就算提前判断了也还是有可能靠不住,
可能判断时剩下一次,到真正调用时却又没了,
毕竟天知道这个 ip 有几个人在用,
AoEiuV020CN
2023-02-28 19:07:16 +08:00
mylovesaber
2023-02-28 21:28:03 +08:00
@AoEiuV020CN 这样 ok 了,还是不减次数的舒服啊,直接筛选出来就是数字,根本不用 string 转 int

githubGetRateInfo=$(curl -s https://api.github.com/rate_limit|xargs|grep -o "rate: {.*.}"|sed 's/,/\n/g; s/{/\n/g; s/}/\n/g; s/ \+//g')
postLimit=$(echo "${githubGetRateInfo}" | awk -F ':' /^limit/'{print $2}')
postRemaining=$(echo "${githubGetRateInfo}" | awk -F ':' /^remaining/'{print $2}')
mylovesaber
2023-02-28 21:29:50 +08:00
@AoEiuV020CN 公司都是搭建的 gitlab ,不用 github ,所以我自己调用问题不大,不过还是感谢分享,否则之前用的那个调一次少一次
julyclyde
2023-03-01 11:26:25 +08:00
echo -n ${postLimit}|hexdump -C
00000000 36 30 0d |60.|
可以看出来 postLimit 变量里面最后含有一个 0d
所以,为什么
echo "GitHub 调用速率为 ${postLimit} 次 /小时"
的结果是
次 /小时用速率为 60
呢?


echo "GitHub 调用速率为 ${postLimit} 次 /小时" |hexdump -C
00000000 47 69 74 48 75 62 20 e8 b0 83 e7 94 a8 e9 80 9f |GitHub .........|
00000010 e7 8e 87 e4 b8 ba 20 36 30 0d 20 e6 ac a1 20 2f |...... 60. ... /|
00000020 e5 b0 8f e6 97 b6 0a |.......|
00000027

看起来输出内容是对的,但是显示效果有问题
geelaw
2023-03-02 11:32:29 +08:00
@julyclyde #34 CR 的作用是“回车”,也就是把光标移动到行开头,在 CR 之后继续打印,自然会踩踏先前的内容。理同 ab BKSP cd 看起来是 acd 一样。
julyclyde
2023-03-02 12:05:20 +08:00
@geelaw 所以问题是出在“只回车 没换行”?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/919678

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX