user2150250
user2150250

Reputation: 5157

Extracting field from last row of given table using sed

I would like to write a bash script to extract a field in the last row of a table. I will illustrate by example. I have a text file containing tables with space delimited fields like ...

Table 1 (foobar)
num  flag  name   comments
1    ON    Frank  this guy is frank
2    OFF   Sarah  she is tall
3    ON    Ahmed  who knows him

Table 2 (foobar)
num  flag  name   comments
1    ON    Mike   he is short
2    OFF   Ahmed  his name is listed twice

I want to extract the first field in the last row of Table1, which is 3. Ideally I would like to be able to use any given table's title to do this. There are guaranteed carriage returns between each table. What would be the best way to accomplish this, preferably using sed and grep?

Upvotes: 0

Views: 378

Answers (4)

Ed Morton
Ed Morton

Reputation: 203229

Just read each block as a record with each line as a field and then print the first sub-field of the last field of whichever record you care about:

$ awk -v RS= -F'\n' '/^Table 1/{split($NF,a," "); print a[1]}' file
3

$ awk -v RS= -F'\n' '/^Table 2/{split($NF,a," "); print a[1]}' file
2

Upvotes: 2

Chris Seymour
Chris Seymour

Reputation: 85775

Awk is perfect for this, print the first field in the last row for each record:

$ awk '!$1{print a}{a=$1}END{print a}' file
3
2

Just from the first record:

$ awk '!$1{print a;exit}{a=$1}' file
3

Edit:

For a given table title:

$ awk -v t="Table 1" '$0~t{f=1}!$1&&f{print a;f=0}{a=$1}END{if (f) print a}' file
3

$ awk -v t="Table 2" '$0~t{f=1}!$1&&f{print a;f=0}{a=$1}END{if (f) print a}' file
2

Upvotes: 4

William
William

Reputation: 4935

This sed line seems to work for your sample.

table='Table 2'
sed -n "/$table"'/{n;n;:next;h;n;/^$/b last;$b last;b next;:last;g;s/^\s*\(\S*\).*/\1/p;}' file

Explanation: When we find a line matching the table name in $table, we skip that line, and the next (the field labels). Starting at :next we push the current line into the hold space, get the next line and see if it is blank or the end of the file, if not we go back to :next, push the current line into hold and get another. If it is blank or EOF, we skip to :last, pull the hold space (the last line of the table) into pattern space, chop out all but the first field and print it.

Upvotes: 2

jyz
jyz

Reputation: 6199

Better tool to that is awk!
Here is a kind legible code:

awk '{
    if(NR==1) {
        row=$0;
        next;
    }

    if($0=="") {
        $0=row;
        print $1;
    } else {
        row=$0;
    }
} END {
    if(row!="") {
        $0=row;
        print $1;
    }
}' input.txt

Upvotes: -1

Related Questions