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
    – PjMpire
    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.

Not the answer you're looking for? Browse other questions tagged .