0

For the below scripts, domains.txt is a text document that contains two lines:

google.com
adsfadsfad.net

I spent about two hours trying to troubleshoot why I couldn't get my grep within a if [[ ]] test to return what I was looking for:

#!/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

The above script would constantly indicate that both domains exist:

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

I confirmed that the following two tests worked perfectly fine from the 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

I then confirmed that if I edited the script by removing the variable and replacing it with adsfadsfad.net, it produced the result I was looking for:

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

adsfadsfad.net is expired

Finally, I settled on just running this test, which produces the correct results:

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

But my question is, why did the variable $domain break my script?

David W
  • 555
  • 2
  • 5
  • 17
  • 2
    `'No match for "$domain"'` suppresses parameter expansions and looks literally for `"$domain"`. Also, your whole `[[ ... ]]` construct checks if the command substitution within it produces an empty string or not; to use grep in a condition, check its exit status instead with `if whois -h "$domain" | grep -q '...'; then` – Benjamin W. Apr 08 '19 at 14:43

3 Answers3

1

Because it was inside single quotes. That tells the shell not to interpolate the text inside, and thus the $domain remains literally dollar sign and the word domain. You need to remove it from the single quotes to get it to work:

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

Or, in this case, because you don't need the single quotes at all:

if [[ $(whois -H "$domain" | grep -i "No match for $domain" ) ]]
Tanktalus
  • 21,664
  • 5
  • 41
  • 68
  • Reading the 'possible duplicate' thread, as well as your answer, oddly enough, when I edit that line to: if [[ $(whois -H $domain | grep -i "No match for $domain") ]]; then The script still comes back, indicating both domains exist. Perhaps I'm still missing something. – David W Apr 08 '19 at 14:50
  • 1
    @DavidW Because you removed the inner quotes: `grep -i "No match for domain \"$domain\""` – mickp Apr 08 '19 at 14:58
1

You don't need [[ ... ]]. grep's exit status alone is sufficient for the if statement.

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

Since you are testing grep's exit status, and not its output, you can suppress the output with the -q flag.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • I've confirmed that this is the case when I don't include the variable, but as soon as I add the pesky $domain back into the grep, it breaks. As others have pointed out, there's a difference between single and double quotes around variables, but as of now, I haven't been able to produce consistent, correct results when using either with the variable. I'll just stick with my actual test (leaving the variable off), and will try to study these answers some more later. Thank you! – David W Apr 08 '19 at 15:10
  • Editing to fix quotes. – chepner Apr 08 '19 at 15:12
0

As already mentioned, bash does not evaluate the expression inside ', and you also want to preserve the double quotes. One thing you can do is to close the ' temporarily for the variable, then continue the text after it was evaluated:

#!/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

I also changed the text a bit so it matches to what the whois command prints.

Ankari
  • 609
  • 5
  • 8