0

Im trying to develop a script that finds a specific pattern in the output of the dig command running against a list of domains. To do this I'm using grep but having difficulty implementing this using multiple logical operations.

I want to achieve something like this:

if output contains ("NXDOMAIN") and ("test1.com" or "test2.com"); then
echo output;

I have managed to get it working for the pattern "NXDOMAIN" by piping the output into grep but I am lost on how to implement the logical operators. My script so far:

#!/bin/bash
input="/root/subdomains.txt"
while IFS= read -r line
do
    output=$(dig "$line")
    if echo "$output" | grep "NXDOMAIN" >&/dev/null; then
        echo "$output";
    else
        echo " " >&/dev/null;
    fi
done < "$input"

Is using grep the best way to achieve this?

2 Answers 2

2

No need for grep or bash here.

#!/bin/sh -
input="/root/subdomains.txt"

contains() {
  case "$1" in
    (*"$2"*) true;;
    (*) false;;
  esac
}

while IFS= read <&3 -r line
do
    output=$(dig "$line")
    if
      contains "$output" NXDOMAIN && {
        contains "$output" test1.com || contains "$output" test2.com
      }
    then
      printf '%s\n' "$output"
    fi
done 3< "$input"

If you really wanted to use grep, you'd define contains as:

contains() {
  printf '%s\n' "$1" | grep -qFe "$2"
}

But that would be less efficient as it means spawning two extra processes and in most sh implementation executing an external grep utility.

Or:

#!/bin/sh -
input="/root/subdomains.txt"

match() {
  case "$1" in
    ($2) true;;
    (*) false;;
  esac
}

while IFS= read <&3 -r line
do
    output=$(dig "$line")
    if
      match "$output" '*NXDOMAIN*' &&
        match "$output" '*test[12].com*'
    then
      printf '%s\n' "$output"
    fi
done 3< "$input"

Or do without the intermediary function:

#!/bin/sh -
input="/root/subdomains.txt"

while IFS= read <&3 -r line
do
    output=$(dig "$line")
    case $output in
      (NXDOMAIN)
        case $output in
          (test1.com | test2.com) printf '%s\n' "$output"
        esac
    esac
done 3< "$input"

That would also work with bash, but there's no need to add a dependency to bash when your (presumably faster and leaner) standard sh can do it.

1
  • thank you for the detailed answer. "match" seemed to do the trick for me Commented Jun 5, 2019 at 9:15
0

You can create a logical AND by piping into grep again, and a logical OR using regular expressions:

echo "$output" | grep "NXDOMAIN" | grep -E 'test1\.com|test2\.com'
2
  • 1
    grep -E "[test1.com|test2.com]" looks for any single character in the set t e s 1 . c o m | 2. You'd need grep -E 'test1\.com|test2\.com' or grep 'test[12]\.com' to look for either test1.com or test2.com Commented Jun 5, 2019 at 8:46
  • 2
    That approach only works if the NXDOMAIN and test[12].com are on the same line. Commented Jun 5, 2019 at 8:46

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.