将日志输出更改为linux中的配置文件

时间:2014-08-22 16:51:06

标签: regex linux bash awk

基本上我有一个DHCP服务器日志的输出,如下所示:

  hardware ethernet 00:16:41:ef:9e:47;
  client-hostname "mo-10";
  hardware ethernet 00:11:25:73:20:a5;
  client-hostname "mo-11";
  hardware ethernet 00:11:25:73:20:a5;
  client-hostname "mo-11";
  hardware ethernet 00:11:25:73:20:a5;
  client-hostname "mo-11";
  hardware ethernet 00:16:41:ef:9e:47;
  client-hostname "mo-10";
  hardware ethernet 00:11:25:73:21:35;
  client-hostname "mo-23";

每两行汇集在一起​​ - 第一行是网络上设备的MAC地址,第二行是主机名。我想取列表,并将每对行放入我的dhcp服务器的配置块中,如下所示:

    host mo-10 {
            hardware ethernet 00:16:41:ef:9e:47;
            fixed-address 192.168.1.10;
    }

主机之后的部分应与客户机主机名相同,硬件以太网块应相同,固定地址应始终为192.168.1.x,其中x是主机名中的数字(因此对于主机mo- 10 ip应该是192.168.1.10,mo-23应该是192.168.1.23等。)所有内容都应该用大括号括起来。另外还有很多重复的条目,我想删除。我试着用grep和awk搞砸了,但是我不太精通在bash中操作文本,这对我来说太复杂了。如果有人能提供一种方法来解决这个问题并解释它为何起作用,我会很高兴。

非常感谢。

4 个答案:

答案 0 :(得分:3)

这是一种方法:

awk '
NR%2 { eth = $0; next }
{ gsub(/[";]/,""); map[$NF] = eth }
END {
    for (host in map) {
        split (host, t, /-/);
        print "host " host " {\n\t" map[host], RS, "\tfixed-ethernet 192.168.1."t[2]";" RS "}"
    }
}' file
host mo-10 {
    hardware ethernet 00:16:41:ef:9e:47;
    fixed-ethernet 192.168.1.10;
}
host mo-11 {
    hardware ethernet 00:11:25:73:20:a5;
    fixed-ethernet 192.168.1.11;
}
host mo-23 {
    hardware ethernet 00:11:25:73:21:35;
    fixed-ethernet 192.168.1.23;
}

将奇数行存储在变量eth中。对于偶数行,删除引号和;并创建一个键值为主机名的哈希值,其值为line。在END块中,您遍历哈希并在-上拆分主机名。

然后您只需打印所需的输出。

答案 1 :(得分:0)

你可以使用sed。要删除重复项,我建议使用管道:

sed '/hardware/{N;s/\n/ /}' < list | sort -k5 | uniq -f4 | sed -r 's/ *hardware ([^ ]*) ([^;]*); *.*"(.*\-(.*))";/host \3 {\n\thardware \1 \2;\n\tfixed-address 192.178.10.\4;\n}/'

管道将每行记录的两行记录展​​平为一行,然后将它们改为sort / uniq,然后重新发送sed以进行最终格式化。

输出:

host mo-10 {
    hardware ethernet 00:16:41:ef:9e:47;
    fixed-address 192.178.10.10;
}
host mo-11 {
    hardware ethernet 00:11:25:73:20:a5;
    fixed-address 192.178.10.11;
}
host mo-23 {
    hardware ethernet 00:11:25:73:21:35;
    fixed-address 192.178.10.23;
}

顺便说一句,毕竟我更喜欢awk解决方案,因为它不需要一次又一次地迭代数据。 (在给出此答案的第一个版本时,没有阅读删除重复限制。)

答案 2 :(得分:0)

下一个:

perl -lanE '
    if(/^\s*$/){$.--;next}  #skip empty lines
    push @v, map {s/[^\da-f:]//ig;$_} $F[$.%2+1] }{ %h=@v;  #process    
#print
say qq[host mo-$h{$_} {
    hardware ethernet $_;
    fixed-address 192.168.1.$h{$_};
}] for keys %h

' <<EOF
hardware ethernet 00:16:41:ef:9e:47    ;

client-hostname "mo-10"   ;

hardware ethernet 00:11:25:73:20:a5;

client-hostname "mo-11" ;
hardware ethernet 00:11:25:73:20:a5 ;
client-hostname "mo-11";
hardware ethernet 00:11:25:73:20:a5;
client-hostname "mo-11";
hardware ethernet 00:16:41:ef:9e:47;

client-hostname "mo-10";
hardware ethernet 00:11:25:73:21:35;
client-hostname "mo-23";
EOF

打印

host mo-23 {
    hardware ethernet 00:11:25:73:21:35;
    fixed-address 192.168.1.23;
}
host mo-10 {
    hardware ethernet 00:16:41:ef:9e:47;
    fixed-address 192.168.1.10;
}
host mo-11 {
    hardware ethernet 00:11:25:73:20:a5;
    fixed-address 192.168.1.11;
}

答案 3 :(得分:0)

在Python中:

import re, sys

template='''\
host {} {{ 
   hardware ethernet {}
   fixed-address 192.168.1.{};
}}'''

pat=re.compile(r'hardware ethernet ([^;]+;)\nclient-hostname ([^;]+;)')

with open(sys.argv[1], 'r') as fin:
    di={k.rstrip(';').strip('"'):v 
            for v, k in pat.findall(fin.read())}

for k, v in di.items():
    ip=re.search(r'(\d+)$', k).group(1)
    print template.format(k, v, ip)

从Bash开始,运行python ip.pl log.txt打印:

host mo-23 { 
   hardware ethernet 00:11:25:73:21:35;
   fixed-address 192.168.1.23;
}
host mo-11 { 
   hardware ethernet 00:11:25:73:20:a5;
   fixed-address 192.168.1.11;
}
host mo-10 { 
   hardware ethernet 00:16:41:ef:9e:47;
   fixed-address 192.168.1.10;
}

通过将主机名数据添加到dict来执行重复删除,该dict只能为每个键值提供一个值。