3

Extracting results from a command in a terminal

I ran a nmap scan on my local network using this command:

nmap -sP 192.168.1.*

When I ran that command I get something that looks similar to this:

Nmap scan report for macbook.att.net (192.168.1.21)
Host is up (0.019s latency).
MAC Address: 71:DF:4B:44:80:F1 (Apple)
Nmap scan report for lenovo.att.net (192.168.1.15)
Host is up (0.045s latency).
MAC Address: 21:EA:7D:84:08:A1 (Liteon Technology)

How can I run that command, but only output the results like this:

1. Apple (192.168.1.21)
2. Liteon Technology (192.168.1.15)

What I have tried so far

So far, I have tried to use grep, but it's not working out as well as I expected. I just need to know how to take the results from that nmap scan and organize it in a list with just what's between the "( )" and also the IP Address.

6

You could try with 'awk' command as follow,

nmap -sP 192.168.1.* | awk -F"[)(]" '/^Nmap/{Nmap=$(NF-1); C+=1} /^MAC Address/{print C"."$(NF-1) "("Nmap")" }' 

output,

1. Apple (192.168.1.21)
2. Liteon Technology (192.168.1.15)

explanations:

  • with awk's -F open your are telling 'awk' that your inputs are delimited with ( and/or ), as what we specified within groups of delimiters -F"[)(]"

  • the '/.../{...} /.../{...}', it's awk's script body, which in your case it will only run first /^Nmap/{Nmap=$(NF-1); C+=1}, or second /^MAC Address/{print C"."$(NF-1) "("Nmap")" }or none of these two condition parts where we specified only run if input string or line starts ( ^ which is the start line anchor and pointing to the beginning of a line/record) with Nmap (or in second part MAC Address) patterns. any match found it will go to run the codes within its braces {...}

what the first part is doing?
As explained above, if match found, then hold the second last feild (NFpointing the last feild(or its returning number of feilds in a record based on defined delims, and $NF its value) value into variable Nmap with $(NF-1); the C+=1 is a counter flag variable we used to count number of matches also at the end using for ID list in output

what the second part is doing?
same as above, but when match found ^MAC Address, then first print counter C value, print a point ., next print the second last feild of matched line and at the end print the value of 'Nmap' within paranteces which is IP of previous matched line

  • ...Nailed It! Do you think you could explain a little bit of what makes this work? – iamr00t Jul 25 '17 at 3:35
  • @AFSHIN - May have been a little more clear if you called the variable Nmap what it captures, IP. – Deathgrip Jul 25 '17 at 3:50
  • 1
    @AFSHIN This helps a lot. Before posting this on the Stack Exchange, I was looking into it for at least 8 hours, and you managed to solve it all from your phone lol. I work in Linux a lot so I'm trying to understand scripting and text-processing as much as possible, so the explanation was much appreciated. – iamr00t Jul 25 '17 at 16:43
  • 1
    once we understand the things, we can do everything we want : ) – αғsнιη Jul 25 '17 at 16:47
3

You could use the xml output format:

nmap -n -sP -oX - 192.168.1.0/24 | xmlstarlet sel -t \
  -m //host \
  -v address/@vendor \
  -o ' (' -v 'address[@addrtype="ipv4"]/@addr' -o ')' -n
3

Using awk would be the preferred way. Nice one liner. But just to show another solution:

#!/bin/bash

COUNTER=0
IP=
COMPANY=

nmap -sP 192.168.1.* | while read line
do
    if [[ "$line" =~ ^Nmap ]]; then
        IP=$(echo "$line" | sed -e "s/.*(\(.*\))/\1/")
    fi
    if [[ "$line" =~ ^MAC ]]; then
        COMPANY=$(echo "$line" | sed -e "s/.*(\(.*\))/\1/")
        COUNTER=$((COUNTER+1))
        echo "${COUNTER}. ${COMPANY} (${IP})"
        IP=
        COMPANY=
    fi
done

Explanation of sed commands:

The first sed command extracts the IP Address from the lines with the format Nmap scan report for macbook.att.net (192.168.1.21). The sed command uses a somewhat simple regex (I should have also used anchors and character classes to be sure I was extracting an IP) with a capture group. The first part of the sed command (between the first and second /) is string to be matched, .*(\(.*\)). The .*( matches any (or no characters) followed by an open parenthesis. The capture group is next, this is \(.*\) which captures any number of characters (in a production environment this should change to a regex that matches the format of an IP Address). The end of the complete regex is a single ). The second part of the sed command (between the second and third /) is what the regex gets replaced with. In this case, just \1 which indicates whatever was in the first capture group.

The second sed command is basically the same thing, which is to say "match the string that contains a set of parenthesis at the end, replace the whole string with what was inside the parenthesis.

What is tricky is that when you are not using the flag to use extended regular expressions, the ( and ) are literal. Open and close parenthesis. They need to be escaped, \( and \), to indicate they are being used for grouping.

Lastly the -e option I use in the command. In this case it's optional since each sed command only has one script/regex to match. It's a habit of mine to always use it.

Suggested reading, man pages regex(3), regex(7) which is sometimes referred to as re_format(7), and the O'Reilly book "Mastering Regular Expressions" by Jeffrey Friedl.

  • Another good one. It's nice to see different ways of solving a problem like this. I will deffinitely try to learn what makes each part of this script work, especially the 'sed' section of it. – iamr00t Jul 25 '17 at 4:02
  • I have been examining this code since you posted it, and I'm having a little trouble wraping my head around the 'sed' part of it. Do you think you could explain how the 'sed' part is formating the text?... or more specifically what -e and all the symbols do? – iamr00t Jul 27 '17 at 22:43
  • @iamr00t - Explanation posted in the answer. Hope it is clear and understandable. – Deathgrip Jul 28 '17 at 18:01
  • Thank you @Deathgrip. I'm looking into the that book now, can't seem to find a free pdf version of it so I might just buy it, if it will really help with stuff like this. – iamr00t Jul 28 '17 at 23:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.