Linux 如何格式化ifconfig的输出

Linux 如何格式化ifconfig的输出,linux,bash,sed,Linux,Bash,Sed,我需要将命令ifconfig-a的结果转换为以下格式 IFACE eth0 192.168.30.8 Ethernet IFACE eth1 212.233.112.171 Ethernet IFACE lo 127.0.0.1 Local Loopback IFACE pan0 0.0.0.0 Ethernet IFACE tunl0 0.0.0.0 IPIP Tunnel 我知道我应该使用sed或类似的工具来实现这一点。 目前,我有以下“脚本”: 原始的ifconfig-a输出是(..表

我需要将命令
ifconfig-a
的结果转换为以下格式

IFACE eth0 192.168.30.8 Ethernet
IFACE eth1 212.233.112.171 Ethernet
IFACE lo 127.0.0.1 Local Loopback 
IFACE pan0 0.0.0.0 Ethernet
IFACE tunl0 0.0.0.0 IPIP Tunnel
我知道我应该使用
sed
或类似的工具来实现这一点。 目前,我有以下“脚本”:

原始的
ifconfig-a
输出是(
..
表示ommited部分)

此转换的第一个问题是IP地址位于接口名称和类型的第二行。A使用
-N
参数concat行,但它们成对concat,如果接口的名称在奇数行上-我有麻烦:脚本跳过奇数行上的接口,如下所示(请注意,输出中没有提及pan0):

第二个问题是,当
ifconfig-a
输出中没有IP地址时,我不知道如何插入零地址。

我得到了一些东西

ifconfig -a | tr -s ' ' | awk -F'[: ]' '
  {if (/^[a-z]/) printf "IFACE " $1 " " $4}
  {if (/inet addr:/) print " " $4}'
说明:

  • tr-s'
    删除多个空格
  • -F'[:]'
    定义了多个分隔符:
    (空格)
  • {if(/^[a-z]/)…
    每当某些事物以字母开头时,打印字段1和4
  • {if(/inet addr:/)…
    每当某些内容包含
    \u inet addr\u
    时,打印字段$4
输出:

IFACE lo Local127.0.0.1
IFACE wlan0 Ethernet192.168.1.61
IFACE eth0 192.168.30.8 Ethernet
IFACE eth1 212.233.112.171 Ethernet
IFACE lo 127.0.0.1 Local Loopback
IFACE pan0 0.0.0.0 Ethernet
IFACE tunl0 0.0.0.0 IPIP Tunnel

正如您所看到的,它们的顺序不同,但我无法获得它。

请注意,
ifconfig
输出随平台而异,因此这不是一种非常便携的方法

至于sed解决方案,我认为您需要将解析分解为多个步骤,类似的方法应该可以工作(GNU sed):

解析

s/^([^]+)*/\1\n/#接口名称
s/链接封装:(.*)(|$)./\1/#链接封装
N#将下一行附加到PS
/inet addr/!s/\n[^\n]*$/\n0.0.0\n/#如果没有“inet addr”,则使用0.0.0.0
s/*inet地址:([^]+)./\1\n/#捕获ip地址(如果存在)
s/\n[^\n]*$/#清除最后一行
s/([^\n]+)\n([^\n]+)\n([^\n]+)/IFACE\1\3\2/p#打印条目
s/*/#空PS
:loop#\
N#\
/^\n$/b#跳到下一个空行
s/*/#/
b环/
解释

其思想是使用换行符捕获模式空间中的所有相关信息

测试

像这样跑:

ifconfig -a | sed -rf parse.sed
ifconfig -a | awk -f parse.awk RS='\n\n' FS=' {2,}|\n'
输出:

IFACE lo Local127.0.0.1
IFACE wlan0 Ethernet192.168.1.61
IFACE eth0 192.168.30.8 Ethernet
IFACE eth1 212.233.112.171 Ethernet
IFACE lo 127.0.0.1 Local Loopback
IFACE pan0 0.0.0.0 Ethernet
IFACE tunl0 0.0.0.0 IPIP Tunnel
IFACE eth0 192.168.30.8以太网
IFACE eth1 212.233.112.171以太网
IFACE lo 127.0.0.1本地环回
IFACE pan0.0.0.0以太网
IFACE tunl0 IPIP隧道

我已经接受了雷神的答案,但这是我的解决方案,有点不同。我在等待答案时仔细考虑了一下

ip addr | sed -r ':a;N;$!ba;s/\n\s/ /g' | sed -r -n -e 's/^([0-9]+):\s(\w+).*(link\/(\w+))\s[a-f0-9:.]{,17}\sbrd\s[a-f0-9:.]{,17}\s*(inet\s([0-9]{1,3}(\.[0-9]{1,3}){3})).*/IFACE \2 \6 \4/p' -e 's/^([0-9]+):\s(\w+).*(link\/(\w+))\s[a-f0-9:.]{,17}\sbrd\s[a-f0-9:.]{,17}.*/IFACE \2 0.0.0.0 \4/p'
输出:

IFACE lo 127.0.0.1 loopback
IFACE eth0 192.168.30.8 ether
IFACE eth1 212.233.112.171 ether
IFACE pan0 0.0.0.0 ether
IFACE tunl0 0.0.0.0 ipip
主要优点——可以按原样调用。第二个优点是接口的顺序与接口索引一致(我是在比较
ifconfig
ip addr
的结果时得到的)


但是Thorn的解决方案更具可读性和可维护性。

为了获得更好的可读性和可维护性,您可以使用awk。GNU awk有一种方法:

解析.awk

函数get2(s){
拆分(s,a,“:”)
返回a[2]
}
{
link=ip=“”

对于(i=2;我认为您应该从
ip addr
的输出开始。然后您需要以类似的方式解析它。
ip addr
输出也有相同的问题-
ip地址
位于设备名称之后的下一行(关于第一个问题,您可以使用
awk'FNR==number_of_line{print}“
要选择行号。哇!一个问题,0.0.0.0被检测词“广播多播”取代,对吗?如果未明确设置
inet addr:
,是否可以将此行为更改为插入0.0.0.0?@AntonBoritskiy:这简化了一点,请查看更新版本我想查看Thor vs steve:)
IFACE eth0 192.168.30.8 Ethernet
IFACE eth1 212.233.112.171 Ethernet
IFACE lo 127.0.0.1 Local Loopback
IFACE pan0 0.0.0.0 Ethernet
IFACE tunl0 0.0.0.0 IPIP Tunnel