3

I use the following command to get the arp table. I now want to add the localhost's ip and MAC address to the output. How should I write the shell script?

arp | grep -v 'incomplete' | tail -n+2 | awk '{print $1"*"$4}'

So the results look like below(it adds iface and host ip to each line of arp table entry)

 eno16777736 192.168.140.133 192.168.140.254,00:50:56:ef:2d:57
 eno16777736 192.168.140.133 192.168.140.2,00:50:56:ea:cf:bf
vaj oja
  • 1,151
  • 2
  • 16
  • 47

2 Answers2

3

On my system, I can do:

arp | 
awk 'NR>1{mac[$NF]=mac[$NF]" "$3} END {for (iface in mac) print iface, mac[iface]}' | 
while read iface mac; do
    inet=$(
        ifconfig "$iface" |
        awk -v i=$iface '{for (j=1; j<NF; j++) if ($j == "inet") {print $(j+1); exit}}'
    )
    echo $iface $inet ${mac// /,}
done
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
0

The easiest way to get the MAC and IP address information for a local interface is the 'ifconfig' command, usually located at '/sbin/ifconfig'. In my case, I am using wlan0 as my primary interface:

# /sbin/ifconfig wlan0
wlan0     Link encap:Ethernet  HWaddr 86:75:30:9a:09:87
          inet addr:10.20.30.40  Bcast:10.20.30.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1276663 errors:0 dropped:0 overruns:0 frame:0
          TX packets:820927 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1233280913 (1.2 GB)  TX bytes:105410513 (105.4 MB)

The simplest example to get your desired output uses a combination echo/grep/sed/awk:

echo $(/sbin/ifconfig wlan0 | \
grep -oE "(HWaddr\ |inet\ addr:)[0-9a-fA-F:\.]+" | \
sed 's/^\(HWaddr \|inet addr\:\)//') | \
awk '{print $2"*"$1}'

Synopsis:

Using the '-o' option in grep will output only what is matched within the line, rather than the line itself.

The '-E' tells grep to expect an "extended regular expression" in the matching criteria. In this case, we are looking for entries starting with "HWaddr " or "inet addr:", followed by any combination of the characters '0-9', 'a-z', 'A-Z', ':, or '.'.

If you end the command there, you are left with two lines that look like "HWaddr 86:75:30:9a:09:87" and "inet addr:10.20.30.40".

We only want the MAC and IP addresses, so we tell sed to get rid of "HWaddr " and "inet addr:" from the beginning of the line ('^' means the beginning).

Capturing the output from this command by wrapping it in '$()' makes the two lines into one line, separated by a space. Adding this to an 'echo' command allows us to use awk to replace the space with a '*', making the final output similar to what your original 'arp | awk' command does.

What we are left with is a this:

# echo $(/sbin/ifconfig wlan0 | grep -oE "(HWaddr\ |inet\ addr:)[0-9a-fA-F:\.]+" | sed 's/^\(HWaddr \|inet addr\:\)//') | awk '{print $2"*"$1}'
10.20.30.40*86:75:30:9a:09:87

You can also do it in pure Bash script, by using its embedded regular expression engine:

# IFS=$'\n' echo $(IFS=$'\n';
for LINE in $(ifconfig wlan0);
do if [[ "${LINE}" =~ .*(HWaddr\ |inet\ addr:)([0-9a-fA-F\:\.]+) || "${LINE}" =~ .*inet\ addr:([\d\.]+) ]];
then echo ${BASH_REMATCH[2]};
fi; done) | \
awk '{print $2"*"$1}'
172.16.17.40*a0:88:b4:78:65:04

...but it's more painful to explain :-P