找到一个单词作为模式给出另一个单词,awk,perl,sed,grep?

时间:2015-07-29 19:49:04

标签: regex bash perl awk sed

美好的一天。

很抱歉这个问题的标题,但我很难解释这一点。

我有一个类似这样的文件(数百台服务器)

mainserver1
--virtualserver1
---- container1
---- container2
--virtualserver2
--virtualserver3
---- container3
---- container4
---- container5
-- virtualserver4
---- container6
---- container7
---- container8
---- container9
---- container10
---- container11
---- container12
---- container13
mainserver2
mainserver3
mainserver4
--virtualserver5
---- container14
---- container15
--virtualserver6
--virtualserver7
mainserver5
mainserver6

这意味着我有:

physicals servers
--virtual servers running on the physcal servers
---- containers (zones/dockers) running on virtual servers

姓名可以有所不同,我作为向导" - "," ----"以[a-z]开头的物理主机。

并且您可以注意到" - virtualserverx"之间没有空格。在" ---- continerx"

中有一个

我想找一些服务器并获取父服务器。

预期输出

./find_parent_server.sh container10
mainserver1
--virtualserver4
---- container10

./find_parent_server.sh virtualserver4
mainserver1

./find_parent_server.sh mainserver1
mainserver1 is a Physical server (i think i can manage this)

有可能吗?

我尝试使用grep,然后尝试使用perl,但是没有像我预期的那样工作,但总比没有好。

tac allservers | perl -lne 'print if /container10/ .. /^[a-z]/'
---- container10
---- container9
---- container8
---- container7
---- container6
-- virtualserver4
---- container5
---- container4
---- container3
--virtualserver3
--virtualserver2
---- container2
---- container1
--virtualserver1
mainserver1

预先感谢一些亮点!

6 个答案:

答案 0 :(得分:3)

@ARGV是给出的参数,因此,在您./find_parent_server.pl container10的情况下,container10中可以找到$ARGV[0]shift关闭它允许使用神奇的<>,它从STDIN读取或提供文件名。

use feature qw{ say } ;
use strict ;
use warnings ;

my $input = shift
    or die("usage\n") ;

my $host = '' ;
my $virt = '' ;
while (<>) {
    chomp ;
    elsif (m{([^-\s]\S*)}) {
        $host = $1;
        next if $host ne $input;

        say $host ;
        }
    elsif (m{^--\s*([^-\s]\S*)}) {
        $virt = $1;
        next if $virt ne $input;

        say $host ;
        say "-- $virt" ;
        }
    elsif (m{^----\s*([^-\s]\S*)}) {
        my $container = $1;
        next if $container ne $input;

        say $host ;
        say "-- $virt" ;
        say "---- $container" ;
        }
    }

如果您的名字中包含空格,请将[^-\s]\S*替换为[^-\s].*

答案 1 :(得分:3)

更新

这是一个直接回答您问题的程序

use strict;
use warnings;

my $wanted = shift or die <<__USAGE__;
Usage:
    $0 <server name>

__USAGE__

my @ancestry;

open my $fh, '<', 'servers.txt' or die $!;

my $found;

while ( <$fh> ) {

  next unless / (-*) \s* (\S+) /x;
  my $index = length($1) / 2;
  $ancestry[$#ancestry = $index] = $2;

  if ( $2 eq $wanted ) {
    if ( @ancestry == 1 ) {
      printf "%s is a Physical server\n", $2;
    }
    else {
      printf "%s %s\n", '--' x $_, $ancestry[$_] for 0 .. $#ancestry;
    }
    ++$found;
    last;
  }
}

printf "Server %s is unknown\n", $wanted unless $found;

输出

>find_parent_server container10
 mainserver1
-- virtualserver4
---- container10

>find_parent_server virtualserver4
 mainserver1
-- virtualserver4

>find_parent_server mainserver1
mainserver1 is a Physical server

>find_parent_server container16
Server container16 is unknown

原始

这是一种构建哈希的方法,该哈希使用您自己的数据将每个节点与其父节点相关联。它期望服务器文件作为命令行上的参数。如果您需要任何帮助来使用生成的哈希,请说出来

use strict;
use warnings;

my ( @ancestry, %parents );

while ( <> ) {
  next unless / (-*) \s* (\S+) /x;
  my $index = length($1) / 2;
  $ancestry[$#ancestry = $index] = $2;
  $parents{$2} = $index ? $ancestry[-2] : 'NONE';
}

use Data::Dump;
dd \%parents

输出

{
  container1     => "virtualserver1",
  container10    => "virtualserver4",
  container11    => "virtualserver4",
  container12    => "virtualserver4",
  container13    => "virtualserver4",
  container14    => "virtualserver5",
  container15    => "virtualserver5",
  container2     => "virtualserver1",
  container3     => "virtualserver3",
  container4     => "virtualserver3",
  container5     => "virtualserver3",
  container6     => "virtualserver4",
  container7     => "virtualserver4",
  container8     => "virtualserver4",
  container9     => "virtualserver4",
  mainserver1    => "NONE",
  mainserver2    => "NONE",
  mainserver3    => "NONE",
  mainserver4    => "NONE",
  mainserver5    => "NONE",
  mainserver6    => "NONE",
  virtualserver1 => "mainserver1",
  virtualserver2 => "mainserver1",
  virtualserver3 => "mainserver1",
  virtualserver4 => "mainserver1",
  virtualserver5 => "mainserver4",
  virtualserver6 => "mainserver4",
  virtualserver7 => "mainserver4",
}

答案 2 :(得分:2)

可能用正则表达式 -

来做
 # (?ms)(?|^($item)()()|^(\w+)(?:(?!^\w).)*?^(--\h*$item)()|^(\w+)(?:(?!^\w).)*^(--\h*\w+)(?:(?!^\w).)*?^(----\h*$item))

 (?ms)
 (?|
      ^ 
      ( $item )                     # (1)
      ( )                           # (2)
      ( )                           # (3)
   |  
      ^ 
      ( \w+ )                       # (1)
      (?:
           (?! ^ \w )
           . 
      )*?
      ^  
      ( -- \h* $item )              # (2)
      ( )                           # (3)
   |  
      ^ 
      ( \w+ )                       # (1)
      (?:
           (?! ^ \w )
           . 
      )*
      ^  
      ( -- \h* \w+ )                # (2)
      (?:
           (?! ^ \w )
           . 
      )*?
      ^  
      ( ---- \h* $item )            # (3)
 )

Perl片段:

use strict;
use warnings;

$/ = undef;
my $servers = <DATA>;

my @ary = ( 'container10', 'virtualserver4', 'mainserver1');

foreach my $item ( @ary )
{
    if ( $servers =~ /(?ms)(?|^($item)()()|^(\w+)(?:(?!^\w).)*?^(--\h*$item)()|^(\w+)(?:(?!^\w).)*^(--\h*\w+)(?:(?!^\w).)*?^(----\h*$item))/ )
    {
        print "Found '$item' :\n";
        print "$1\n" if (length($1));
        print "$2\n" if (length($2));
        print "$3\n" if (length($3));
        print "\n";
    }
}


__DATA__

mainserver1
--virtualserver1
---- container1
---- container2
--virtualserver2
--virtualserver3
---- container3
---- container4
---- container5
-- virtualserver4
---- container6
---- container7
---- container8
---- container9
---- container10
---- container11
---- container12
---- container13
mainserver2
mainserver3
mainserver4
--virtualserver5
---- container14
---- container15
--virtualserver6
--virtualserver7
mainserver5
mainserver6

输出:

Found 'container10' :
mainserver1
-- virtualserver4
---- container10

Found 'virtualserver4' :
mainserver1
-- virtualserver4

Found 'mainserver1' :
mainserver1

答案 3 :(得分:1)

将其存储在树形结构中的哈希值中,然后根据您的需要进行打印。小心library(data.table)#v1.9.5+ setDT(Test)[, Best_Bid_Ex:= Bid[1L], rleid(!is.na(Tick))] Test # Tick Bid Best_Bid_Ex # 1: NA 393.75 393.75 # 2: NA 393.75 393.75 # 3: NA 393.75 393.75 # 4: NA 394 393.75 # 5: NA 394 393.75 # 6: 1 NA NA # 7: NA 394 394 # 8: NA 394 394 # 9: NA 394 394 #10: NA 394 394 #11: NA 393.75 394 #12: -1 NA NA #13: NA 393.75 393.75 #14: NA 393.75 393.75 --,即你不应该在那里放置额外的空格。

----

一样使用它
#!/usr/bin/perl

use strict;
use warnings;

my %hash = ();
my $key1;
my $key2;

while ( <DATA> ) {

    chomp;

    if ( /^[a-z]+/ ) {
        $key1 = $_;
        $hash{$key1} = {};
    }

    if ( /^--[a-z]+/ ) {
        $key2 = $_;
        $key2 =~ s/--//g;
        $hash{$key1}{$key2} = [];
    }

    if ( /^---- [a-z]+/ ) {
        $_ =~ s/---- //g;
        push( @{ $hash{$key1}{$key2} }, $_ );
    }
}

my $server = $ARGV[0];
my $flag   = 0;

foreach my $key ( keys %hash ) {

    foreach my $nkey ( keys %{ $hash{$key} } ) {

        if ( $server eq $nkey ) {
            $flag = 1;
            print "$key \n--$server \n";
            last;
        }
        elsif ( grep { $server eq $_ } @{ $hash{$key}{$nkey} } ) {
            $flag = 1;
            print "$key \n--$nkey \n---- $server \n";
            last;
        }
    }
}

print "Oops!! No Such server \n" if ( $flag == 0 );

__DATA__
mainserver1
--virtualserver1
---- container1
---- container2
--virtualserver2
--virtualserver3
---- container3
---- container4
---- container5
--virtualserver4
---- container6
---- container7
---- container8
---- container9
---- container10
---- container11
---- container12
---- container13
mainserver2
mainserver3
mainserver4
--virtualserver5
---- container14
---- container15
--virtualserver6
--virtualserver7
mainserver5
mainserver6

输出:

perl script.pl container10

答案 4 :(得分:0)

用sed解决方案。 (是的,它很难看,但有效)

(read -p "Search term: " servername;tac list_of_servertree.txt |sed -n "/$servername$/,/^[a-z]/p"|tr '\n' ' ';echo)|sed -e 's/\([^\-]\)\ \([a-zA-Z]\)/\1\n\2/1' -e 's/\(^\|\ \)\(--\ \{0,1\}[a-zA-Z]\)/\n\2/1' |sed 's/^\(-\+[^\-]\+\).*/\1/g'|grep -v '^$'

答案 5 :(得分:0)

受@ sln正则表达式解决方案的启发。

T=container10 perl -0777 -ne 
   'print/.*(^\w\S+.)(?:.*^(--\w\S+.).*?^(---- )|.*?^(--))($ENV{T}\b.)/ms' server.list

捕获组对应于您想要的输入。贪婪的.*表达式会占用您不想要的所有输入,并且在目标表达式之前使用非贪婪的.*?