说我有一个bash脚本,如下所示,它的目的是将所有参数连接到命令字符串,然后执行此命令。如您在下面看到的,加入的命令无法成功执行,我认为我没有正确处理带引号的字符串。我想知道为什么以及如何纠正它。
脚本:
$ cat testarg.sh
#!/bin/bash
echo "args number: $#"
args="$@"
cmd=""
#way 1, loop over $@
for arg in $args
do
echo "arg: $arg"
cmd="$cmd $arg"
done
ttt=""
#way 2, use shift built-in
while [[ $# -gt 0 ]]
do
k="$1"
shift
echo "k: $k"
ttt="$ttt $k"
done
echo "args: $args"
echo "cmd: $cmd"
echo "ttt: $ttt"
$ttt
使用curl命令运行脚本的输出(失败):
$ testarg.sh curl -k -X POST -H "Content-Type: application/json" -d '{"username":"admin", "password": "passw0rd"}' "https://localhost:8443/token/generate"
args number: 9
arg: curl
arg: -k
arg: -X
arg: POST
arg: -H
arg: Content-Type:
arg: application/json
arg: -d
arg: {"username":"admin",
arg: "password":
arg: "passw0rd"}
arg: https://localhost:8443/token/generate
k: curl
k: -k
k: -X
k: POST
k: -H
k: Content-Type: application/json
k: -d
k: {"username":"admin", "password": "passw0rd"}
k: https://localhost:8443/token/generate
args: curl -k -X POST -H Content-Type: application/json -d {"username":"admin", "password": "passw0rd"} https://localhost:8443/token/generate
cmd: curl -k -X POST -H Content-Type: application/json -d {"username":"admin", "password": "passw0rd"} https://localhost:8443/token/generate
ttt: curl -k -X POST -H Content-Type: application/json -d {"username":"admin", "password": "passw0rd"} https://localhost:8443/token/generate
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
curl: (3) [globbing] unmatched close brace/bracket in column 11
{
"timestamp" : "2018-10-31T02:05:48.333+0000",
"status" : 415,
"error" : "Unsupported Media Type",
"message" : "Content type 'application/octet-stream' not supported",
"path" : "/token/generate"
}
因此,看来我无法在“ $ @”上循环,然后重新加入它们,它用多个元素拆分了引用的字符串。因此,我使用shift内置程序,将引用的字符串保留下来。
直接运行上面的$ ttt字符串时输出相同(失败):
$ curl -k -X POST -H Content-Type: application/json -d {"username":"admin", "password": "passw0rd"} https://localhost:8443/token/generate
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
curl: (3) [globbing] unmatched close brace/bracket in column 9
{
"timestamp" : "2018-10-31T02:29:24.973+0000",
"status" : 415,
"error" : "Unsupported Media Type",
"message" : "Content type 'application/octet-stream' not supported",
"path" : "/token/generate"
}
直接运行完全相同的curl命令(成功)时的输出:
$ curl -k -X POST -H "Content-Type: application/json" -d '{"username":"admin", "password": "passw0rd"}' "https://localhost:8443/token/generate"
{
"token" : "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJBRE1JTklTVFJBVE9SIiwianRpIjoiYTE0MWZmMTAtZjNlMi00ZDVhLWFjOGUtODE1Y2YzNzYyNzA0IiwiaXNzIjoiaHR0cDovL2libS5jb20iLCJpYXQiOjE1NDA5NTE1NDAsImV4cCI6MTU0MTAzNzk0MH0.plrjsVAPaRSU6K2WnlTCy-6V1iuSK01F6SULH4lELqs"
}
我想加入所有参数的原因是将来我想向另一个传递的curl命令添加标头。例如添加身份验证令牌。
例如,假设用户要运行以下curl命令:
testarg.sh curl -k -X POST -H "Content-Type: application/json" -d '{"key": "value"}' "https://localhost:8443/protected_page"
然后使用testargs.sh,将auth标头添加到curl命令中,最后执行curl命令:
curl -H "Authorization: Bearer <token>" -k -X POST -H "Content-Type: application/json" -d '{"key": "value"}' "https://localhost:8443/protected_page"
谢谢。
答案 0 :(得分:1)
将"$@"
复制到常规变量会破坏您在该变量中的所有引用。您想直接循环"$@"
,或者如果确实确实需要先复制它,则将其复制到数组中。
答案 1 :(得分:1)
args="$@"
将所有参数合并为一个:
$ set -- foo 'bar baz'
$ printf '%q\n' "$args"
foo\ bar\ baz
您可以设置args=("$@")
:
$ args=("$@")
$ printf '%q\n' "${args[@]}"
foo
bar\ baz
甚至更好的是,完全避免引用-for arg
是for arg in "$@"
的语法糖。