Ribs
Ribs

Reputation: 53

Extract string under a string from a file in linux

This site have helped me a lot in the past but signed up only now as I couldn't find an exact answer for what am trying now. I hope you would be able to help.

I'm trying to extract or cut the values under a string in a file. My file looks like:

Xmqqstab v1.0 - Developed by Oliver Fisse (ISSW)

 ****
 **** Tuesday, April 26, 2016 10:49:21 AM BST ****
 ****
       UNIX
 Report for queue(s): 'Q1' on queue manager 'QMGR'...

        CQD     PQF      MxQD   OIC   OUC    UNC  LGETDATE  LGETTIME  LPUTDATE  LPUTTIME  QOM G P   Local Queue Name
 ----------------------------------------------------------------------------------------------------------------------------------------------------
          5   0.10%      5000     0     0      0 2016-04-26 10.48.46 2016-04-26 10.49.01  26s E E - Q1

              1 queue(s) matching.

The file actually gives MQ queue statistics and am trying to get the values under say, CQD=5 (this could be any digit number), LGETTIME=10.48.46.

I could get the line with the values using: grep -A3 'CQD' file.txt | sed -n '3p'. And from the line I will have to cut the values by column but I thought it wont be accurate to do so as the digits could vary like 5 in this case could be a four digit number in which case the column numbers would change.

I hope am clear with the question.

Would appreciate any help.

Thanks.

Upvotes: 4

Views: 182

Answers (4)

Gergely Bacso
Gergely Bacso

Reputation: 14651

The simplest solution would be just replacing your multiple spaces with a delimiter of your choice, and then cut would work reliably, just as you planned it first:

grep -A3 'CQD' file.txt | sed -n '3p' | sed 's/  */_/g'  | cut -f2 -d'_'

This is the part that replaces multiple spaces with underscore:

sed 's/  */_/g' 

Upvotes: 0

Cole Tierney
Cole Tierney

Reputation: 10324

Assuming the data you're interested in is the 1st line that starts with a digit:

read my_CQD my_LGETDATE <<< $(awk '$1 ~ /^[0-9]/ {print $1, $8; exit}' file.txt)

Explanation:

The awk program watches for a line whose first field begins with a digit. It then prints the 1st and 8th fields separated by a space then quits. Bash reads these two values into $my_CQD and $my_LGETDATE.

Output:

echo -e "\$my_CQD: $my_CQD\n\$my_LGETDATE: $my_LGETDATE"
$my_CQD: 5
$my_LGETDATE: 10.48.46

Upvotes: 0

Tom Fenech
Tom Fenech

Reputation: 74685

You could go for something like this:

awk '/CQD/ { for (i = 1; i <= NF; ++i) if ($i == "CQD") col = i } col && $col == 5' file

On the line matching the field name of interest, loop through each field to find the column that contains it. When col has been set and the value in the column matches the one you want, print the line (the default action).

You could pass the heading and value as parameters to the script if you wanted:

awk -v heading=CQD -v value=5 '$0 ~ heading { 
    for (i = 1; i <= NF; ++i) if ($i == heading) col = i 
} col && $col == value' file

Using either of these approaches, the output is the line:

          5   0.10%      5000     0     0      0 2016-04-26 10.48.46 2016-04-26 10.49.01  26s E E - Q1

...which I'm assuming is what you're looking for!

Upvotes: 3

sat
sat

Reputation: 14949

With sed:

sed -rn '/CQD.*LGETTIME/{n;n; s/^ *([^ ]* *)([^ ]* *){6}([^ ]*).*/\1\3/p}'

Output:

$ sed -rn '/CQD.*LGETTIME/{n;n; s/^ *([^ ]* *)([^ ]* *){6}([^ ]*).*/\1\3/p}' file
5   10.48.46

Upvotes: 0

Related Questions