文件services
- 包含许多类似这样的记录:
define service {
host_name\t\t\t\tHOSTNAME
...
...
}
文件hosts
- 包含记录:
define host {
host_name\t\t\t\tHOSTNAME
...
...
}
我需要转到hosts
,以某种方式从第一条记录中获取HOSTNAME的名称,然后转到文件services
并找到包含该HOSTNAME的所有记录并将它们放到其他文件中。然后为hosts
中的每个HOSTNAME执行此操作。
我不知道的主要是如何从文件主机获取HOSTNAME,然后如何在文件服务中获取变量的整个记录。我准备了一个正则表达式(希望它是正确的)^define.*host_name\t\t\t\t$HOSTNAME.*}
请给我一些建议或示例如何获得想要的结果。
答案 0 :(得分:3)
您提供的文件与nagios配置文件非常相似。
sed可能是你的朋友,因为它允许你将文件切成更小的部分,例如:
:t
/^define service {/,/}$/ { # For each line between these block markers..
/}$/!{ # If we are not at the /end/ marker
$!{ # nor the last line of the file,
N; # add the Next line to the pattern space
bt
} # branch (loop back) to the :t label.
} # This line matches the /end/ marker.
/host_name[ \t]\+HOSTNAME\b/!d; # delete the block if wrong host.
}
该示例从sed faq 4.21中解除,并略微适应。您还可以查看问题4.22,它似乎直接解决了这个问题:
http://sed.sourceforge.net/sedfaq4.html#s4.22
与之前的答案一样,我也倾向于说你最好使用其他脚本语言。如果你需要一个不同的翻译来完成这项任务,不妨使用你知道的东西。
答案 1 :(得分:2)
这个任务对于bash脚本来说有点过于复杂。我会使用Perl:
#!/usr/bin/perl
use warnings;
use strict;
open my $SRV, '<', 'services' or die $!;
open my $HST, '<', 'hosts' or die $!;
my %services;
{ local $/ = "\n}";
while (my $service = <$SRV>) {
my ($hostname) = $service =~ /^\s*host_name\t+(.+?)\s*$/m;
push @{ $services{$hostname} }, $service if defined $hostname;
}
}
while (my $line = <$HST>) {
if (my ($host) = $line =~ /^\s*host_name\t+(.+?)\s*$/) {
if (exists $services{$host}) {
print "===== $host =====\n";
print "$_\n" for @{ $services{$host} };
} else {
warn "$host not found in services!\n";
}
}
}