Kalin Borisov
Kalin Borisov

Reputation: 1120

Get string from two rows

Want to convert output to variables, from the first row want to take every time the last result.

There are 1 server(s) in cluster: SQL_GDM
MS_SQL_sql1.local.com---RUNNING
There are 2 server(s) in cluster: MONGO_GDM
MS_MONGO1_mongo1.local.com---RUNNING
MS_MONGO2_mongo2.local.com---RUNNING

Expected view:

SQL_GDM|sql1.local.com|RUNNING
MONGO_GDM|mongo1.local.com|RUNNING
MONGO_GDM|mongo2.local.com|RUNNING

For now I just take only the state of the servers with:

grep -oP '(?<=---)\w+'

I'm wondering how to remove MS_*_ and to stay only the host and after that to grep the state of the server.

Upvotes: 2

Views: 125

Answers (5)

Chris Seymour
Chris Seymour

Reputation: 85875

Here is one way:

$ awk '/^There/{a=$(NF-1)"_"$NF;next}{print a,$3,$NF}' FS='[ _-]' OFS='|' file
SQL_GDM|sql1.local.com|RUNNING
MONGO_GDM|mongo1.local.com|RUNNING
MONGO_GDM|mongo2.local.com|RUNNING

Explanation:

  • FS='[ _-]' separate each record into fields using spaces, underscores and hyphens as field separators.
  • OFS='|' separate the output fields using the pipe symbol.
  • /^There/{a=$(NF-1)"_"$NF;next} If the line starts with There store the last two fields separated by an underscore in the variable a and grab the next line.
  • {print a,$3,$NF} for lines that don't start There print the value of a, the third field and last field.

Upvotes: 4

Vijay
Vijay

Reputation: 67301

perl -lne 'if(/cluster: ([\S]*)/){$a=$1}elsif(/_.*_(.*?)---(.*)/){print "$a|$1|$2"}' your_file

Tested below

> cat temp
There are 1 server(s) in cluster: SQL_GDM
MS_SQL_sql1.local.com---RUNNING
There are 2 server(s) in cluster: MONGO_GDM
MS_MONGO1_mongo1.local.com---RUNNING
MS_MONGO2_mongo2.local.com---RUNNING
> perl -lne 'if(/cluster: ([\S]*)/){$a=$1}elsif(/_.*_(.*?)---(.*)/){print "$a|$1|$2"}' temp
SQL_GDM|sql1.local.com|RUNNING
MONGO_GDM|mongo1.local.com|RUNNING
MONGO_GDM|mongo2.local.com|RUNNING

Upvotes: 4

Steve P.
Steve P.

Reputation: 14709

Toy example:

use strict;
use warnings;

my $inputFile = shift(@ARGV);
open (my $input, $inputFile);

my $cluster = undef;

  while(<$input>)
  {
    chomp;

    if ($_ =~ /^There are \d+ server\(s\) in cluster: (\w+)$/)
    { 
        $cluster = $1; #keeps track of current cluster
    }

    else 
    {
        $_ =~ s/.*_.*_//; #removes the underscores and non-sense associated with them

        if ($_ =~ /---([A-Z]+)/)
        {
            my $temp = $1; #extracts RUNNING or NOT_RUNNING, or what have you

            $_ =~ s/---$temp//; #removes hypens/STATE from $_

            print "$cluster|$_|$temp\n";
        }
    }
  }

Comments are in the code. I assumed that there is one entry per line. If you put your input into a file and open it as $input, it will produce the exact output that you desired. If you need more explanation, leave a comment.

Upvotes: 2

Ian Kenney
Ian Kenney

Reputation: 6436

you can remove the MS_*_ by piping the output through sed

echo "MS_MONGO1_mongo1.local.com---RUNNING" |  sed "s/^MS_.*_//" 

or create an awk script convert.awk

/cluster:/{ cluster = $NF; }
/^MS_/{ 
  gsub("---","|"); 
  gsub("^MS_.*_",""); 
  printf("%s|%s\n",  cluster,$0); 
}

and pipe your output through

awk -f convert.awk

Upvotes: 4

Birei
Birei

Reputation: 36282

One way with . It uses a regular expression to split fields, one or more hyphens (-+) or a colon followed by optional spaces characters (:[[:space:]]*). That way is easier to find either the cluster and the state. For the server I split with _ and extract last path.

Content of script.awk:

BEGIN {
        FS = "-+|:[[:space:]]*"
}

$0 ~ /:/ {
        cluster = $NF
        next
}

{
        n = split( $1, server, /_/ )
        printf "%s|%s|%s\n", cluster, server[ n ], $NF
}

Run it like:

awk -f script.awk infile

And it yields:

SQL_GDM|sql1.local.com|RUNNING
MONGO_GDM|mongo1.local.com|RUNNING
MONGO_GDM|mongo2.local.com|RUNNING

Upvotes: 5

Related Questions