Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String Bash字符串比较不求值为true_String_Bash_Comparison - Fatal编程技术网

String Bash字符串比较不求值为true

String Bash字符串比较不求值为true,string,bash,comparison,String,Bash,Comparison,我有一个脚本,我想找出HTTP请求的状态代码。然而,if语句的计算结果从来都不是true,我不明白为什么 #!/bin/sh set -e CURL='/usr/bin/curl' CURL_ARGS='-o - -I -s' GREP='/usr/bin/grep' url="https://stackoverflow.com" res=$($CURL $CURL_ARGS $url | $GREP "HTTP/1.1") echo $res # This outputs 'HTTP

我有一个脚本,我想找出HTTP请求的状态代码。然而,
if
语句的计算结果从来都不是true,我不明白为什么

#!/bin/sh

set -e

CURL='/usr/bin/curl'
CURL_ARGS='-o - -I -s'
GREP='/usr/bin/grep'

url="https://stackoverflow.com"

res=$($CURL $CURL_ARGS $url | $GREP "HTTP/1.1")

echo $res # This outputs 'HTTP/1.1 200 OK'
echo ${#res} # This outputs 16, even though it should be 15

if [ "$res" == "HTTP/1.1 200 OK" ]; then # This never evaluates to true
  echo "It worked"
  exit 1
fi

echo "It did not work"
我检查了
res
的长度,它是16,我在浏览器的控制台中检查了它,它是15,所以我通过删除两端的空白对它进行了修剪,但结果仍然不是真的

res_trimmed="$(echo "${res}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
它仍然不起作用


有什么不对劲吗?感谢您的帮助。谢谢。

您的问题是,您的命令替换返回的结果中出现了错误字符。要消除,请仅匹配有效字符,例如

GREP='/usr/bin/grep -o'
...
res=$($CURL $CURL_ARGS $url | $GREP 'HTTP/1.1[A-Za-z0-9 ]*')
其他变化

echo "'$res'" # This outputs 'HTTP/1.1 200 OK'
示例使用/输出

$ sh curltest.sh
'HTTP/1.1 200 OK'
15
It worked

更好的实践实现可能如下所示:

#!/usr/bin/env bash
#              ^^^^- ensure that you have bash extensions available, rather than being
#                    only able to safely use POSIX sh syntax. Similarly, be sure to run
#                    "bash yourscript", not "sh yourscript".

set -o pipefail  # cause a pipeline to fail if any component of it fails

url="https://stackoverflow.com"

# curl -f == --fail => tell curl to fail if the server returns a bad (4xx, 5xx) response
res=$(curl -fsSI "$url" | grep "HTTP/1.1") || exit
res=${res%$'\r'}  # remove a trailing carriage return if present on the end of the line

if [ "$res" = "HTTP/1.1 200 OK" ]; then
  echo "It worked" >&2
  exit 0            # default is the exit status of "echo". Might just pass that through?
fi

echo "It did not work" >&2
exit 1

顺便说一句,将命令片段存储在字符串变量中是一种糟糕的形式。另外,由于shell是
/bin/sh
而不是
bash
,因此不能假定
==
是有效的。(此外,如果有意的话,您可能应该标记问题
sh
,而不是
bash
。(POSIX还指出,all caps变量名称空间用于对操作系统或shell有意义的变量,并保留小写名称供应用程序使用——请参见第四段)。(
GREP='/usr/bin/GREP'
如今也被认为是一种反模式,这不仅仅是因为大小写可变。现代Shell——意味着过去30年的价值——缓存路径查找,因此没有显著的性能提升,但自从决定是否将给定的二进制文件放入
/bin
o之后,移植性受到了影响r
/usr/bin
在不同的发行版之间往往会有所不同)…顺便说一句,在bash中,
printf'%q=%q\n'res“$res”
可以更准确地描述名为
res
的变量中的实际内容。(
declare-pres
在Bash4.x中也能工作,并添加了关于变量类型和标志的额外细节,但在某些3.x shell中,它会逐字发出某些不可打印的字符,而不是转义它们;如果其中一个字符是您的罪魁祸首,那就没什么帮助了)。具体地说,
curl
s输出通常具有DOS/Windows样式的行结尾,带有回车符,后跟换行符。Unix工具将回车符视为行的一部分(第16个字符)。这确实解决了OP狭义解释的问题,但也没有确切地展示最佳实践。@CharlesDuffy这方面的最佳实践是什么?请提供文档链接或SO帖子。@simeg,…我添加了一个单独的答案。@CharlesDuffy,是的,同意,(必须运行接孩子…)。BASH FAQ/50链接解决了片段问题。最初,解释器将答案限制在POSIX上,但正如您所展示的,BASH中有许多更改可以改进处理能力,还有更多…顺便说一句,
如果curl--fail“$url”;那么echo“success”;否则echo“failure”如果您只想知道结果是否反映HTTP错误,那么;fi
实际上可能就足够了,根本不需要对输出进行grep。