how to write `awk here document`

1

2

I have a bash script:

#!/bin/bash

gawk -f realmap.awk realmap.log | column -ts: > realmap.csv

gnuplot <<-_EOF_
    set term png
    set out 'realmap.png'
    set xlabel 'index'
    set ylabel 'bytes'
    set style data lp
    plot 'realmap.csv' u 1:2 t col, '' u 1:3 t col, '' u 1:4 t col, '' u 1:5 t col, '' u 1:6 t col, '' u 1:7 t col
_EOF_

rm realmap.csv

display realmap.png

And a awk script:

#!/usr/bin/gawk -f

BEGIN{
    printf("%s:%s:%s:%s:%s:%s:%s\n", "index", "total", "used", "free", "cached", "buffers", "cache")
}

/^#/{
    gsub("#", "")
    printf("%d:", $0+1)
}

/^M/{
    printf("%d:%d:%d:%d:", $2,$3,$4,$7)
}

/^-/{
    printf("%d:%d\n", $3, $4)
}

How to combine these two scripts as one?

kev

Posted 2011-12-07T04:51:05.920

Reputation: 9 972

what do u mean by combine??? Combination depends on what functionality u want to achieve... – Vineet Menon – 2011-12-07T05:30:57.030

Answers

1

You don't need a "here document". Just place the entire awk program — properly quoted so that all of the quotation marks and metacharacters within it are not recognized by the shell and so that the linefeeds and other whitespace don't cause it to be split into multiple arguments by the shell — as the first command-line argument, without using awk's -f option. Without -f, the first command line argument is the program to run. The awk manual page is your friend.

JdeBP

Posted 2011-12-07T04:51:05.920

Reputation: 23 855

2Do you have an example? – David Given – 2016-09-21T19:25:48.250

7

Note:

The self consuming script pattern in the 2nd code sample can be used for ANYTHING that reads a file. Don't be distracted by the OP's use of awk.

Answer:

What you asked for was a heredoc. It's tricky to use in this case, but I love heredocs so I'm going to show you how to do it. You have to incorporate an even lesser known bash feature, process substitution with <()

#!/bin/bash

  # The <( begins a process substitution. It's valid to use with -f because what gets
  # substituted is a file descriptor like /dev/fd/5
  # The quoting on '_EOF_' prevents the shell from expanding the contents of the heredoc,
  # as if it were a big double quoted string. So, your $2, $3, etc. are safe.
gawk -f <(cat - <<-'_EOF_'
    BEGIN{
        printf("%s:%s:%s:%s:%s:%s:%s\n", "index", "total", "used", "free", "cached", "buffers", "cache")
    }

    /^#/{
        gsub("#", "")
        printf("%d:", $0+1)
    }

    /^M/{
        printf("%d:%d:%d:%d:", $2,$3,$4,$7)
    }

    /^-/{
        printf("%d:%d\n", $3, $4)
    }
_EOF_
) realmap.log | column -ts: > realmap.csv

gnuplot <<-_EOF_
    set term png
    set out 'realmap.png'
    set xlabel 'index'
    set ylabel 'bytes'
    set style data lp
    plot 'realmap.csv' u 1:2 t col, '' u 1:3 t col, '' u 1:4 t col, '' u 1:5 t col, '' u 1:6 t col, '' u 1:7 t col
_EOF_

rm realmap.csv

display realmap.png

So that is the answer you asked for. Now, the way I would do it is with what I call the self consuming script pattern.

#!/bin/bash

  # The <( begins a process substitution. It's valid to use with -f because what gets
  # substituted is a file descriptor like /dev/fd/5
  # Notice the use of brackets. That prevents the following line from matching itself.
gawk -f <(sed -e '/[B]EGIN_AWK1/,/[E]ND_AWK1/!d' $0) realmap.log | column -ts: > realmap.csv

gnuplot <<-_EOF_
    set term png
    set out 'realmap.png'
    set xlabel 'index'
    set ylabel 'bytes'
    set style data lp
    plot 'realmap.csv' u 1:2 t col, '' u 1:3 t col, '' u 1:4 t col, '' u 1:5 t col, '' u 1:6 t col, '' u 1:7 t col
_EOF_

rm realmap.csv

display realmap.png

exit  ## Execution stops here. The rest is consumed by subprocesses of this script!

#BEGIN_AWK1
    BEGIN{
        printf("%s:%s:%s:%s:%s:%s:%s\n", "index", "total", "used", "free", "cached", "buffers", "cache")
    }

    /^#/{
        gsub("#", "")
        printf("%d:", $0+1)
    }

    /^M/{
        printf("%d:%d:%d:%d:", $2,$3,$4,$7)
    }

    /^-/{
        printf("%d:%d\n", $3, $4)
    }
#END_AWK1

To me that is pretty easy to follow and you can put multiple AWK or and other scripts in one file by incrementing the delimiter.

Enjoy bashing! Feel free to come vist #bash on freenode for even quicker answers.

For more info see http://tldp.org/LDP/abs/html/process-sub.html

Bruno Bronosky

Posted 2011-12-07T04:51:05.920

Reputation: 1 251