为什么使用grep的bash脚本的if [[]]测试在使用变量或字符串时返回不同的结果

时间:2019-04-08 14:39:09

标签: bash grep

对于以下脚本,domains.txt是一个包含两行的文本文档:

google.com
adsfadsfad.net

我花了大约两个小时来尝试解决为什么无法在grep测试中获得if [[ ]]来返回我想要的东西的原因:

#!/bin/bash
declare -a domain

while read domain; do

    if [[ $(whois -H $domain | grep -i 'No match for "$domain"') ]]; then
        echo "$domain is expired"
    else 
        echo "exists"
    fi

done < domains.txt

上面的脚本将不断指示两个域同时存在:

[root@localhost ~]# ./check-dns.sh 
exists 
exists

我确认以下两个测试在shell上运行良好:

#[root@localhost ~]# if [[ $(whois -H adsfadsfad.net | grep -i 'No match for "adsfadsfad.net"') ]]; then echo "true"; else echo "false"; fi
#true
#[root@localhost ~]# if [[ $(whois -H google.com | grep -i 'No match for "google.com"') ]]; then echo "true"; else echo "false"; fi
#false

然后我确认,如果我通过删除变量并将其替换为adsfadsfad.net来编辑脚本,则会产生我想要的结果:

{snip}
if [[ $(whois -H $domain | grep -i 'No match for adsfadsfad.net') ]]; then
{snip}
  

adsfadsfad.net已过期

最后,我决定运行此测试,它会产生正确的结果:

if [[ $(whois -H $domain | grep -i 'No match for') ]]; then

但是我的问题是,为什么变量$domain破坏了我的脚本?

3 个答案:

答案 0 :(得分:1)

因为它在单引号内。这告诉外壳程序不要内插文本,因此$domain仍然是美元符号,而单词domain仍然是美元符号。您需要将其从单引号中删除才能使其正常工作:

if [[ $(whois -H "$domain" | grep -i 'No match for '"$domain" ) ]]

或者,在这种情况下,因为您根本不需要单引号:

if [[ $(whois -H "$domain" | grep -i "No match for $domain" ) ]]

答案 1 :(得分:1)

您不需要[[ ... ]]。对于grep语句,仅if的退出状态就足够了。

if whois -H $domain | grep -iq "No match for \"$domain\""; then
    echo "$domain is expired"
else 
    echo "exists"
fi

由于您正在测试grep的退出状态,而不是其输出,因此可以使用-q标志来禁止输出。

答案 2 :(得分:0)

如前所述,bash不会对'内的表达式求值,并且您还希望保留双引号。您可以做的一件事是暂时关闭变量的',然后在求值后继续执行文本:

#!/bin/bash
declare -a domain

while read domain; do

    if [[ $(whois -H "$domain" | grep -i 'No match for domain "'$domain'"' ) ]]; then
        echo "$domain is expired"
    else
        echo "exists"
    fi

done < domains.txt

我还稍微更改了文本,使其与whois命令打印的内容匹配。