1

I am trying to return a list of IP Addresses for computers that have a windows OS (for my security course). The output is in this format

Nmap scan report for 192.168.xx.xxx
Host is up (0.066s latency).
PORT    STATE SERVICE
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds
MAC Address:

Host script results:
| smb-os-discovery: 
|   OS: Windows Server (R) 2008 Standard 6001 Service Pack 1 (Windows Server (R) 2008 Standard 6.0)
|   OS CPE: cpe:/o:microsoft:windows_server_2008::sp1
|   Computer name: 
|   NetBIOS computer name: 
|   Workgroup: WORKGROUP
|_  System time: 2015-12-22T17:01:33-08:00

I was able to get the values into a better format using grep "for\|Windows"

Nmap scan report for 192.168.xx.xx1
|   OS: Windows XP (Windows 2000 LAN Manager)
Nmap scan report for 192.168.xx.xx5
|   OS: Windows 2000 (Windows 2000 LAN Manager)
Nmap scan report for 192.168.xx.xx8
Nmap scan report for 192.168.xx.x15

I am now trying to get the value (grep) of the previous line, if the next line contains a "|" character, but I have no idea how. I have tried using tr "|" "\b" but that did not work

Input (stored in a text file)

Line 1
|   Line2
Line 3
|   Line 4
Line 5
|   Line 6
Line 7
Line 8
Line 9
|   Line 10
Line 11

Desired Output

Line 1
Line 3
Line 5
Line 9
2
  • 1
    Given your example input as the file input: grep -B1 '|' input | grep -v '|'
    – DopeGhoti
    Dec 30, 2015 at 23:38
  • nmap also has an XML output mode (-oX file.xml) on which you could then use XPath or CSS selectors to pull out what you want.
    – thrig
    Dec 30, 2015 at 23:57

2 Answers 2

2

You could do without grep e.g with sed you could save the line with the IP to hold buffer and copy it over the pattern space only when OS is Windows (deleting all other lines):

... | sed '/^Nmap scan report for/h;/^|[[:blank:]]*OS: Windows/!d;g'

or, in a similar manner, with awk, this time printing only the IP instead of the whole line:

... | awk '/^Nmap scan report for/{t=$5};/^\|[[:blank:]]*OS: Windows/{print t}'
1
sed -e'$!N;/\n|/P;D' \
<<""
Line 1
|   Line2
Line 3
|   Line 4
Line 5
|   Line 6
Line 7
Line 8
Line 9
|   Line 10
Line 11

Line 1
Line 3
Line 5
Line 9

If it gets deeper...

sed -e'/^ *|/!{$!N;/\n|/P;}' -eD \
<<""
Line 1
|   Line2
|   Line 3
|___|   Line 4
    |   Line 5
    |___Line 6
Line 7
Line 8
Line 9
|   Line 10
Line 11

Line 1
Line 9

You can drop grep w/ ...

sed -ne'/^Nmap.* /!{/^|.*: Win.*(W/!d;}' \
    -e's///;/)/H;x;s/\n/: (W/p' \
<<""
Nmap scan report for 192.168.xx.xxx
Host is ...
bla... and more ...
and bla and so on...
#
Host script results:
| smb-os-discovery:
|   OS: not windows Server (R) ... !(Windows Server (R) 2008 Standard 6.0)
|   OS CPE: cpe:/o:microsoft:windows_server_2008::sp1
|   Comp ... some words ...
|   Net... more words ...
|   Work... words again ...
|_  Sys...
#
Nmap scan report for 192.168.xx.xxx
Host is ...
MAC Address:
#
Host script results:
| smb-os-discovery:
|   OS: Windows Server (R) 2008 Standard 6001 Service Pack 1 (Windows Server (R) 2008 Standard 6.0)
|_  System time: 2015-12-22T17:01:33-08:00

192.168.xx.xxx: (Windows Server (R) 2008 Standard 6.0)

You must log in to answer this question.

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