Reputation: 85
UPDATE I need to clarify that Jon8RFC-LT and DOMAIN are also just generic examples of dynamic content, like the IP address and MAC address; nmblookup retrieves and displays entirely dynamic content based on the ip address. If awk is used, I need to have a way to pull 4 dynamic values from the nmblookup: IP, hostname/asset name, domain name, MAC address. Sorry for the confusion, I updated the code to make it more clear.
I have been searching and using my Linux book for a couple of days and cannot find what I need for awk/gawk/grep/egrep/sed (I think I need one or more of those, elegantly). In a bash script, I'm running:
su_nmblookup=$(nmblookup -A $ipaddress)
which returns
WARNING: The "idmap backend" option is deprecated added interface eth0 ip=a07d::a07d:a07d:a07d:a07d%eth0 bcast=b57d::ffff:ffff:ffff:ffff%eth0 netmask=ffff:ffff:ffff:ffff:: added interface eth1 ip=b57d::b57d:b57d:b57d:b57d%eth1 bcast=a07d::ffff:ffff:ffff:ffff%eth1 netmask=ffff:ffff:ffff:ffff:: added interface eth0 ip=234.234.234.234 bcast=12.12.12.12 netmask=255.255.0.0 Socket opened. Looking up status of 123.123.123.123 JON8RFC-LT <00> - B <ACTIVE> DOMAIN <00> - <GROUP> B <ACTIVE> JON8RFC-LT <20> - B <ACTIVE> DOMAIN <1e> - <GROUP> B <ACTIVE> MAC Address = 4F-A2-4F-A2-4F-A2
The best I've managed, is to chop it down with this code:
display=${su_nmblookup/#*Looking/\Looking}
Looking up status of 123.123.123.123 JON8RFC-LT <00> - B <ACTIVE> DOMAIN <00> - <GROUP> B <ACTIVE> JON8RFC-LT <20> - B <ACTIVE> DOMAIN <1e> - <GROUP> B <ACTIVE> MAC Address = 4F-A2-4F-A2-4F-A2
However, what I'd like to know is how to return either of these cleaned up formats. I want to learn how the grep/awk/sed works with extracting data with these two examples, one with preserving the formatting, and one with just new lines. I had a hell of a time even getting the quoting/coding to work properly here because of the formatting and gt/lt symbols!
Looking up status of 123.123.123.123 JON8RFC-LT DOMAIN 4F-A2-4F-A2-4F-A2
OR, simply
JON8RFC-LT DOMAIN 123.123.123.123 4F-A2-4F-A2-4F-A2
Thank you for your help!
Upvotes: 5
Views: 1916
Reputation: 440679
An annotated awk
solution that provides both output formats - prettied and raw - selectable by a variable:
# Set this to:
# * 1 for a "pretty" display with header line and indentation
# * 0 for printing the raw data items only.
pretty=1
awk -v pretty=$pretty '
# Skip lines before "Looking up ..."
!startRow && /Looking up status of / { startRow=NR; }
!startRow { next }
# Parse the lines of interest relative to the "Looking up ..." row.
NR==startRow { ip=$5; header=$0; next } # IP address
NR==startRow+1 { nm=$1; next } # name, e.g.: "JON8RFC-LT"
NR==startRow+2 { dm=$1; next } # domain, e.g.: "DOMAIN"
/MAC Address =/ { ma=$4; exit } # MAC address, e.g.: "4F-A2-4F-A2-4F-A2"
END { # all relevant lines processed; output result
if (pretty) # print with header and indentation
{ print header; print "\t" nm; print "\t" dm; print "\t" ma }
else # print raw data items only
{ print nm; print dm; print ip; print ma }
}' <(nmblookup -A $ipaddress)
A few quick pointers:
-v pretty=$pretty
defines an awk
variable based on a shell variable; note how the awk
program as a whole is enclosed in single quotes to prevent accidental shell expansions inside the awk
program, which should be treated as its own world, separate from the shell.!startRow
: awk
variables in a numeric/Boolean context default to 0
/false
if not yet defined, so this expression evaluates to false
until startRow
is set to a non-zero value./Looking up status of/
is a regex that is matched against the current input line; NR
contains the current, 1-based row (line) number.next
skips remaining pattern/actions for the current line and proceeds to the next line.NR==startRow
is a pattern that evaluates to true if the current line's index matches the value stored in startRow
$1
, for instance, represents the 1st field from the current line - by default, awk
breaks lines into fields - starting with index 1 and the ending index stored in variable NF
- based on whitespace.END
is a special pattern whose associated block is executed after all input lines have been processed; note that an exit
command in a previous action still causes the END
action to be processed.<(...)
is an instance of process substitution which provides the output from any command as a pseudo file.Upvotes: 2
Reputation: 16016
I see you want a grep
/awk
/sed
answer, but you may be interested to know what you need is possible purely with bash builtins:
unset results
declare -A results
while read; do
case $REPLY in
*'Looking up status of '*) ip="${REPLY##* }";;
*'MAC Address = '*) mac="${REPLY##* }";;
*' '*) tmp="${REPLY# }"; results[${tmp%% *}]=1 ;;
esac
done < <(nmblookup -A $ipaddress)
printf "%s\n" ${!results[@]}
echo $ip
echo $mac
This script fragment may be placed in your existing script.
This script reads each line of input and applies a case
switch to match the patterns you are interested in. Each pattern has its own set of commands to format the data you need. In the case of lines that begin with 4 spaces, we use a bash associative array to make sure we only get one of each of the JON8RFC-LT
and DOMAIN
lines.
Note associative arrays require bash 4.0 or more.
Upvotes: 3
Reputation: 7844
Assuming the output of nmblookup -A 123.123.123.123
is redirected to file input.txt
awk '/Looking up status of/ {print} /JON8RFC-LT/ {if(a!=1){print "\t"$1;a=1}} /DOMAIN/ {if(b!=1){print "\t"$1;b=1}} /MAC Address/ {print "\t"$4}' input.txt
Updated as Etan Reisner suggested to be shorter:
awk '/Looking up status of/ {print} /JON8RFC-LT/ && !a {print "\t"$1;a=1} /DOMAIN/ && !b {print "\t"$1;b=1} /MAC Address/ {print "\t"$4}' input.txt
output:
Looking up status of 123.123.123.123
JON8RFC-LT
DOMAIN
4F-A2-4F-A2-4F-A2
Updated for Dynamic content
awk '/Looking up status of/,/MAC Address/ {print; getline;print "\t"$1;getline;print "\t"$1;getline;getline;getline;getline;print "\t"$4;exit 0}' input.txt
Assumes on the two lines after line Looking up ...
you want the first word. Then ignores three lines and then prints MAC address.
Upvotes: 4