1

I've created the function to display interfaces and IP's per interface

network() {
iplst() {
ip a show "$i" | grep -oP "inet\s+\K[\w./]+" | grep -v 127
}
ip ntable | grep -oP "dev\s+\K[\w./]+"| grep -v lo | sort -u >> inf_list
netlist="inf_list"
while read -r i
do
infd=$i
   paste <(echo -e $i) <(iplst)
 done < $netlist
}

Current output:

ens32   10.0.0.2/24
        10.0.0.4/24
        10.0.0.20/24
ens33   192.168.1.3/24
ens34   192.168.0.2/24
ens35   192.168.2.149/24

but would like to avoid creation of temp files, would appreciate suggestions

  • Are you sure you want to *nest* your functions? See, for example, [How to define a function inside another function in bash](http://stackoverflow.com/q/8426077/3266847) – Benjamin W. Mar 14 '17 at 22:42
  • Why are you using `paste` when only one line is being processed at a time? – Charles Duffy Mar 14 '17 at 22:47
  • Also, this code is missing functionality needed for others to be able to test it. For instance, `iplst` is completely undefined. See [How to create a Minimal, Complete, Verifiable Example](http://stackoverflow.com/help/mcve). – Charles Duffy Mar 14 '17 at 22:47
  • @Charles Duffy Because one interface has one interface name and may have 10 IP's, and I need them to be displayed in columns as it is now –  Mar 14 '17 at 22:49
  • "As it is now" -- nobody but you can see that, because your code isn't complete enough for anyone but you to run it. – Charles Duffy Mar 14 '17 at 22:49
  • Ahh; better. Relying on `i` as a global variable is rather... *unfortunate*, by the way -- better to flag it local and pass it around as an explicit argument. – Charles Duffy Mar 14 '17 at 22:51
  • BTW, need I say that `grep -v 127` is a bad idea? `10.1.0.127` is very much an IP address that can exist without loopback involvement. – Charles Duffy Mar 14 '17 at 23:03
  • it does, but it's nothing informative about it, it does exists by default. –  Mar 14 '17 at 23:05
  • @CharlesDuffy , on an other though, you'r right, I'll probably will implement a filter to ignore it only if it is described in lo, thanks –  Mar 14 '17 at 23:14
  • The change I made in my answer -- filtering out `127` only at the *start* of an address, and not in any other position -- is probably sufficient. – Charles Duffy Mar 14 '17 at 23:53

2 Answers2

3

In general, temporary files can be replaced with process substitution. For instance, to avoid the inf_list temporary file, one can generate its contents with an inf_list function:

build_inf_list() {
  ip ntable | grep -oP "dev\s+\K[\w./]+"| grep -v lo | sort -u
}

iplst() {
  ip a show "$1" | grep -oP "inet\s+\K[\w./]+" | egrep -v '^127'
}

while read -r i; do
  paste <(printf '%s\n' "$i") <(iplst "$i")
done < <(build_inf_list)

Some notes:

  • Passing (and using) explicit arguments makes it much more obvious to a reader than relying on globals set elsewhere in your code, and reduce the chances that functions added in the future will stomp on variable names you're depending on.
  • Using process substitution, <(...), is replaced with a filename which, when read from, will return the stdout of the command ...; thus, since what you're writing to your temporary file comes from such a command, you can simply replace the temporary file with a process substitution invocation.
  • Any shell where echo -e does not print -e on its output is defying black-letter POSIX. While bash is noncompliant in this manner by default, it's not noncompliant consistently -- if the posix and xpg_echo flags are both set, then bash complies with the letter of the standard. It's much safer to use printf, which is far more robustly defined. See also the APPLICATION USAGE and RATIONALE sections of the linked standard document, which explains how BSD and AT&T UNIX have traditionally incompatible versions of echo, and thus why the POSIX standard is so loose in the behavior it mandates.
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
0

Final result, thanks @Charles Duffy

#!/bin/bash
build_inf_list() {
  ip ntable | grep -oP "dev\s+\K[\w./]+"| grep -v lo | sort -u
}
iplst() {
if [ "$1" = "lo" ]; then
  ip a show "$1" | grep -oP "inet\s+\K[\w./]+" | grep -v '^127'
else
  ip a show "$1" | grep -oP "inet\s+\K[\w./]+"
fi
}

while read -r i; do
  paste <(printf '%s\n' "$i") <(iplst "$i")
done < <(build_inf_list)

edited

  • As an aside -- `==` isn't actually guaranteed to be supported in `[ ]`; the string comparison operator that's mandated by the POSIX standard is just `=`. See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html – Charles Duffy Mar 15 '17 at 04:53
  • (There's still the outstanding bug about filtering out addresses on `lo` that contain `127` in something other than starting position, too -- if you had `1.2.3.127` assigned to `lo`, you probably don't want `grep -v 127` to be taking it out as if it had been `127.0.0.1`; making that filter `grep -v '^127'` avoids the issue). – Charles Duffy Mar 15 '17 at 04:55