Getting IP from inside parenthesis

I have this script in RHEL 7.9, and $ip is not working well.

for i in $(cat prtqueue)
do
        echo "Queue Name: " $i
ip=`nslookup $i 2>&1 | awk '/^Address/ {print $2}' | tail -n1`
                if ping -c 1 $i > /dev/null 2>&1; then
                  echo "IP         :" $ip Pingble.
                else
                  echo "IP         :" $ip Not Pingble.
                 fi
        echo "----------------------------------------"
done

ip=`nslookup $i 2>&1 | awk '/^Address/ {print $2}' | tail -n1
is the problem where I need to get the actual IP from ping -c1 $i

04:42:10 # ping -c 1 jp18e 
PING jp18e (10.92.195.250) 56(84) bytes of data.
64 bytes from jp18e (10.92.195.250): icmp_seq=1 ttl=52 time=56.6 ms

Can you please let me know how to grab the IP from the ping output, i.e. 10.92.195.250 in this example?

Appreciate your help!

as its PING you want the output from try something along ... (the awk bit)

ping -q -c 1 localhost | awk -F'[()]' '/\([0-9].*\)/{print $2}'
127.0.0.1

So which command do you actually want to use for obtaining the IP address? nslookup or ping?
You can e.g.

ping -c 1 "$hostname" 2>&1 | grep -m 1 -Eo '([0-9]+\.){3}[0-9]+'
for i in $(cat prtqueue)
do
        echo "Queue Name: " $i
ip = `ping -q -c 1 $i | awk -F'[()]' '/\([0-9].*\)/{print $2}'`
                if ping -c 1 $i > /dev/null 2>&1; then
                  echo "IP         :" $ip Pingble.
                else
                  echo "IP         :" $ip Not Pingble.
                 fi
        echo "----------------------------------------"
done

Thank you so much for our feedback.
If I run just this ping -q -c 1 xxxxx | awk -F'[()]' '/\([0-9].*\)/{print $2}
it works fine.

But, if I run this in the loop,
ip = `ping -q -c 1 $i | awk -F'[()]' '/\([0-9].*\)/{print $2}'`

it errors out.
Can you please let me know what I am missing it in the loop?

I can only get the IP from PING, not from nslookup.

ping -q -c 1 xxxxx | awk -F'[()]' '/\([0-9].*\)/{print $2}' works fine as a single line, but not working in the loop.

Can you please let me know what I missed in the loop?

for i in $(cat prtqueue)
do
        echo "Queue Name: " $i
ip= `ping -c 1 $i 2>&1 | grep -m 1 -Eo '([0-9]+\.){3}[0-9]+'`
                if ping -c 1 $i > /dev/null 2>&1; then
                  echo "IP         :" $ip Pingble.
                else
                  echo "IP         :" $ip Not Pingble.
                 fi
        echo "----------------------------------------"
done

whats in the prtqueue file ?

try something like ...

#!/bin/bash

prtqueue=$1

for host in $(cat $prtqueue)
do
  ping -q -o -c 1 $host > /tmp/$host.log 2>&1
  if [ $? == 0 ]
  then
      echo "IP: $host ,  $( head -1 /tmp/$host.log | awk -F'[()]' '/\([0-9].*\)/{print $2}' ) is pingable"
  else
     echo "$host is not pingable"
     tail -1 /tmp/$host.log
  fi

  rm /tmp/$host.log

done

NB: there are a number of ways to achieve, the above is one potential way ...

An assignment is
var=value
No space around the = !!

` ` can cause surprises. Use $( ) instead!

2 Likes

Thank you!
prtqueue has the list of printer queues from the RHEL host.

Aha!! I didn't know will cause issues.
$( ) works a lot better! Thank you!

for i in $(cat prtqueue)
do
        echo "Queue Name: " $i
ip=$(ping -c 1 "$i" 2>&1 | grep -m 1 -Eo '([0-9]+\.){3}[0-9]+')
echo "IP Address:  " $ip
       if ping -c 1 $i > /dev/null 2>&1; then
                  echo "Ping Output: " Pingble.
                else
                  echo "Ping Output: " Not Pingble.
                 fi
        echo "----------------------------------------"
done

This returns the expected output well.

Queue Name: jp18e
IP Address: 10.92.195.250
Ping Output: Pingble.
----------------------------------------
Queue Name: jp18b
IP Address: 10.92.195.253
Ping Output: Pingble.
----------------------------------------
Queue Name: jp18a
IP Address: 10.92.195.254
Ping Output: Pingble.
----------------------------------------
Queue Name: jp18h
IP Address: 10.92.211.252
Ping Output: Pingble.
----------------------------------------
Queue Name: jp18g
IP Address: 10.92.211.253
Ping Output: Pingble.
----------------------------------------
Queue Name: zzztttqqq
IP Address:
Ping Output: Not Pingble.
----------------------------------------

The only question I have is to display the output horizontally.
I am not sure if it is possible. If it is, that will be great!!!

This is what I really want to have:

-----------------------------------------------------------------------
Queue Name:  jp18b  IP Address:   10.92.195.253  Ping Output:  Pingble.
-----------------------------------------------------------------------
Queue Name:  jp18a  IP Address:   10.92.195.254  Ping Output:  Pingble.
-----------------------------------------------------------------------
Queue Name:  jp18h  IP Address:   10.92.211.252  Ping Output:  Pingble.
-----------------------------------------------------------------------
Queue Name:  jp18g  IP Address:   10.92.211.253  Ping Output:  Pingble.
-----------------------------------------------------------------------

Thank you!!

for i in $(cat prtqueue)
do
	ip=$(ping -c 1 "$i" 2>&1 | grep -m 1 -Eo '([0-9]+\.){3}[0-9]+')
	if ping -c 1 $i > /dev/null 2>&1
	then
		echo "Queue Name: $i IP Address: $ip  Ping Output: Pingble."
	else
		echo "Ping Output: $i Not Pingble."
	fi
	echo "----------------------------------------"
done

That is brilliant! Thank you so much!!!

@danielshell1

this

ip=$(ping -c 1 $i 2>&1 | grep -m 1 -Eo '([0-9]+\.){3}[0-9]+')|
if ping -c 1 $i > /dev/null 2>&1|
then

can be reduced to

ip=$(ping -q -o -c 1 "$i" 2>&1 | grep -m 1 -Eo '([0-9]+\.){3}[0-9]+')
if [ ! -z "$ip" ]
then

since $ip will either be null ("") or the ipaddr, so if ping -c 1 $i > /dev/null 2>&1 is superfluous

however, you should be aware that returning an ipaddr is not quite the same as the host being 'pingable', see below - the host is NOT PINGABLE (100% packet loss), the exit status of 2 also indicative of same.

ping -c1 bac.com
PING bac.com (171.159.228.21): 56 data bytes

--- bac.com ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss

echo $?
2

not all hosts are pingable for a variety of reasons.
The ipaddress will (typically) have been resolved via DNS without ever actually 'pinging' the host itself.

all of the above may not matter in your case , am merely sharing for your informaton ....

Thank you so much for the info!!

for i in $(cat prtqueue)
do
	ip=$(ping -c 1 "$i" 2>&1 | grep -m 1 -Eo '([0-9]+\.){3}[0-9]+')
	if ping -c 1 $i > /dev/null 2>&1
	then
	else
		echo "Queue Name: $i IP Address: $ip  Ping Output: Pingble."
	fi
	echo "----------------------------------------"
done

I am trying to have a better output where it only returns the output where the queues are NOT pingable.

How do I update the script?
then needs to be skipped so that the output will have the NON-pingable list with no spaces (no empty rows).

Thank you so much for your help!

Perhaps you can use getent hosts for the host-ip lookup.

    ip=$(getent hosts "$i" | awk '{print $1; exit}')
    if [ -z "$ip" ]
    then
        echo "Queue Name: $i not resolvable"
    elif ping -c 1 "$i" > /dev/null 2>&1
    then
        echo "Queue Name: $i IP Address: $ip  Ping Output: Pingable."
    else
        echo "Ping Output: $i Not Pingable."
    fi

An non ZERO exit status of the ping would indicate the host is not known or unreachable or does not respond to ping requests.

cat danielshell1.sh
#!/usr/local/bin/bash

prtqueue=$1

for host in $(cat $prtqueue)
do
        ping -q -o -c 1 $host > /tmp/$host.log 2>&1
        if [ $? == 0 ]
        then
                : # the colon is a NOOP command in bash shell   
                # echo "$host, IP: $( head -1 /tmp/$host.log | awk -F'[()]' '/\([0-9].*\)/{print $2}' ) is pingable"
        else
                ip=$(head -1 /tmp/$host.log | awk -F'[()]' '/\([0-9].*\)/{print $2}' )
                echo "$host is not pingable, REASON: ${ip:+'host does not respond to ping requests'} $(tail -1 /tmp/$host.log )"
        fi
   
        rm /tmp/$host.log

done

#
# test run
#
./danielshell1.sh hosts 
local1host is not pingable, REASON:  ping: cannot resolve local1host: Unknown host
zzzz.bt is not pingable, REASON:  ping: cannot resolve zzzz.bt: Unknown host
bac.com is not pingable, REASON: host does not respond to ping requests 1 packets transmitted, 0 packets received, 100.0% packet loss
bt.co.uk is not pingable, REASON: host does not respond to ping requests 1 packets transmitted, 0 packets received, 100.0% packet loss

Drive by comment: nslooup vs dig

Consider using dig instead of nslookup. There are many reasons, but the most germane here is that I think the following would give you only the output you want and no need to post process it.

ip=$(dig +short $i)

In my experience, dig is pretty much useless in LAN, while nslookup doesn't care whether the machine is local or "somewhere else in the net".

In my experience, dig is pretty much useless in LAN, while nslookup doesn't care whether the machine is local or "somewhere else in the net".

Please elaborate @Matt-Kita.

What failures have you seen with dig that you have seen nslookup succeed in the same situation.

Both make DNS queries to the configured / specified DNS server.

Sure, a "real-life example" for one of the customers I'm supporting:
image

For WAN - both dig and nslookup work fine, for LAN - dig is pretty much useless (in this particular case). Of course there is a possibility, that it may be specific DNS server configuration, nevertheless...
Cheers!