bash - 如何从文件中查找字符串并获取其位置?

时间:2013-04-19 10:34:03

标签: string bash find

文件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.*}

请给我一些建议或示例如何获得想要的结果。

2 个答案:

答案 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";
        }
    }
}