輸入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
輸出變體,並輸出三個製表符分隔的欄位:介面名稱、IP 位址和 MAC 位址。
如果第二個欄位中有多個 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
注意:您要求的輸出將 192.168.0.2 作為 bond0:0 的 IP 位址,但您的範例資料具有 192.168.0.1,與介面相同bond0
。
如果取消註解腳本中的「可選」行,它將確保始終有 3 個製表符分隔的輸出字段,即使 IP 位址或 MAC 位址字段為空。
輸出如下:
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