入力1
eno16780032: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.1 netmask 255.255.255.255 broadcast 192.168.0.254
ether 00:50:56:00:00:00 txqueuelen 1000 (Ethernet)
eno33559296: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.2 netmask 255.255.255.255 broadcast 192.168.0.254
ether 00:50:56:00:00:01 txqueuelen 1000 (Ethernet)
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 0 (Local Loopback)
入力2
bond0 Link encap:Ethernet HWaddr 00:50:56:00:00:00
inet addr:192.168.0.1 Bcast:192.168.0.254 Mask:255.255.254.255
UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
bond0:0 Link encap:Ethernet HWaddr 00:50:56:00:00:00
inet addr:192.168.0.1 Bcast:192.168.0.254 Mask:255.255.254.255
UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
eth0 Link encap:Ethernet HWaddr 00:50:56:00:00:00
UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1
eth1 Link encap:Ethernet HWaddr 00:50:56:00:00:00
UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
出力は次のようにしたい(基本的には抽出するインターフェース、IP、ハードウェアアドレス)
出力1
eno16780032 192.168.0.1 00:50:56:00:00:00
eno33559296 192.168.0.2 00:50:56:00:00:01
lo 127.0.0.1
出力2
bond0 192.168.0.1 00:50:56:00:00:00
bond0:0 192.168.0.2 00:50:56:00:00:00
eth0 00:50:56:00:00:00 ===> No IP since its under bonding
eth1 00:50:56:00:00:00 ===> No IP since its under bonding
lo 127.0.0.1
awk で試してみました(awk '/flags|Link/{a=$1;hw=$NF;next;} /inet /{ip=$2;print a,ip,hw}'),
が、各行ですべての一致パターンが利用できるわけではないため、目的の出力を取得できませんでした。
したがって、インターフェイスがボンディングの一部であるため、入力 2 ファイルに一致するパターンの空の「inet addr:」を追加すると、問題は解決すると考えられます。
インターフェース行の後に空の「inet addr:」を追加する方法を教えていただけますか?
eth0 Link encap:Ethernet HWaddr 00:50:56:00:00:00 UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 inet addr: <==== Insert empty line
または
- 上記のように目的の出力を取得します。
答え1
awk 'BEGIN { OFS="\t" }; # use tab for output separator
! /^ / { # line doesnt begin with a space, must be an interface line, extract it
i=gensub(/:$/,"",1,$1)
mac[i]=$5; # this will either be a HWAddr or empty
ifaces[i]=1
};
/^ +inet/ { ip[i] = ip[i] " " gensub(/addr:/,"",1,$2) };
/^ +ether/ { mac[i]=$2}; # this will only match if there WASNT a HWAddr on the iface line
END {
for (i in ifaces) {
sub(/^ +/,"",ip[i]); # remove unwanted space from beginning of ip addresses
#if (ip[i] == "") ip[i] = "--"; #optional
#if (mac[i] == "") mac[i] = "--"; #optional
print i, ip[i], mac[i]
}
}' filename | sort
(または、ifconfig
入力ファイル名を指定するのではなく、パイプで入力するだけです)
この awk スクリプトはどちらのifconfig
出力形式も処理でき、タブで区切られた 3 つのフィールド (インターフェース名、IP アドレス、MAC アドレス) を出力します。
2 番目のフィールドに複数の IP アドレスがある場合は、スペースで区切られます。
input1 に対して実行され、パイプされたときの出力sort
:
eno16780032 192.168.0.1 00:50:56:00:00:00
eno33559296 192.168.0.2 00:50:56:00:00:01
lo 127.0.0.1
input2 に対して実行され、パイプされたときの出力sort
:
bond0:0 192.168.0.1 00:50:56:00:00:00
bond0 192.168.0.1 00:50:56:00:00:00
eth0 00:50:56:00:00:00
eth1 00:50:56:00:00:00
lo 127.0.0.1
注: 要求された出力では bond0:0 の IP アドレスとして 192.168.0.2 が指定されていましたが、サンプル データではbond0
インターフェイスと同じ 192.168.0.1 が指定されていました。
スクリプト内の「オプション」行のコメントを解除すると、IP アドレスまたは MAC アドレス フィールドが空の場合でも、常にタブで区切られた 3 つの出力フィールドが存在するようになります。
出力は次のようになります。
eno16780032 192.168.0.1 00:50:56:00:00:00
eno33559296 192.168.0.2 00:50:56:00:00:01
lo 127.0.0.1 --
そして
bond0:0 192.168.0.1 00:50:56:00:00:00
bond0 192.168.0.1 00:50:56:00:00:00
eth0 -- 00:50:56:00:00:00
eth1 -- 00:50:56:00:00:00
lo 127.0.0.1 --
追加コメント:
それは間違いコマンドを無視しますip
。これは何年も前からLinuxの標準であり、インターフェースにセカンダリ/代替/「エイリアス」IPアドレスを追加する多くのプログラムがこれを使用します。この方法でインターフェースに追加されたセカンダリIPアドレスはのみでは表示されますがip addr show
、 を実行すると表示されませんifconfig
。
ifconfig
少なくとも Linux では、レガシーとしてのみ考慮する必要があります。
答え2
素朴ですが効果的な解決策は、出力をifconfig
逆に読むことです。この方法では、ブロックの最初の行に遭遇するたびに、興味のあるフィールドが見つかったか、またはフィールドが欠落していると安全に想定できます。AWK スクリプトを次に示します。
{
for (i = 1; i <= NF; i++) {
if ($i == "inet") {
ip = $(i+1)
sub(/.*:/, "", ip)
}
if ($i == "HWaddr" || $i == "ether")
hw = $(i+1)
}
}
/^[^[:blank:]]/ {
nm = $1
sub(/:$/, "", nm)
print nm,ip,hw
nm = ""
ip = ""
hw = ""
}
これを として保存した場合awkscript
、次のように実行できます。
ifconfig | tac | awk -f awkscript | tac | column -s ' ' -t
非標準のtac
コマンドが使用できない場合は、この AWK スクリプトを簡単に変更して、入力ストリーム全体を配列に保存し、ブロック内で逆順に処理することができますEND
。
答え3
$ cat tst.awk
!/^[[:space:]]/ { if (NR>1) prt() }
{ rec = rec FS $0 }
END { prt() }
function prt( flds,i,nf,map) {
sub(/: /," ",rec)
sub(/ ether /," HWaddr ",rec)
sub(/ inet addr:/," inet ",rec)
nf = split(rec,flds)
map["iface"] = flds[1]
for (i=2; i<nf; i++) {
map[flds[i]] = flds[i+1]
}
print map["iface"], map["inet"], map["HWaddr"]
rec = ""
}
$ awk -f tst.awk file1 | column -s' ' -t
eno16780032 192.168.0.1 00:50:56:00:00:00
eno33559296 192.168.0.2 00:50:56:00:00:01
lo 127.0.0.1
$ awk -f tst.awk file2 | column -s' ' -t
bond0 192.168.0.1 00:50:56:00:00:00
bond0:0 192.168.0.1 00:50:56:00:00:00
eth0 00:50:56:00:00:00
eth1 00:50:56:00:00:00
lo 127.0.0.1