print block of text to file from awk script [banner like]

前端 未结 3 1050
小蘑菇
小蘑菇 2020-12-22 01:13

I have awk script doing some processing and sending it\'s output to a file. How would I writeout in BEGIN block of my awk program a banner-like mes

3条回答
  •  执念已碎
    2020-12-22 01:39

    The simple way is to use a heredoc and save it in an awk variable:

    VAR="whatever"
    awk -v var="\
    #########################################
    #      generated by some author         #
    #        $VAR
    #########################################" '
    BEGIN{ print var }
    '
    #########################################
    #      generated by some author         #
    #        whatever
    #########################################
    

    Alternatively, this may be more than you wanted, but below is the command I use to provide something a bit better than just here docs in awk. I find it absolutely invaluable when adding template text to multiple files..

    It's a shell script which takes an awk script with slightly extended syntax (to facilitate here documents) as input, invokes gawk to transform that extended syntax to normal awk print statements, and then calls gawk again to execute the resulting script.

    I call it "epawk" for "extended print" awk and what follows is the tool plus several examples of how to use it. When you invoke it instead of invoking awk directly you can write scripts that include blocks of pre-formatted text for printing like you'd want to with a here-doc (the space before each # is a tab character):

    $ export VAR="whatever"
    $ epawk 'BEGIN {
        print <<-!
            #########################################
            #      generated by some author         #
            #        "ENVIRON["VAR"]"
            #########################################
        !
    }'
    #########################################
    #      generated by some author         #
    #        whatever
    #########################################
    

    It works by creating an awk script from your awk script and then executing it. If you'd just like to see the script that is being generated, epawk will print the generated script instead of executing it if you give it the -X argument, e.g.:

    $ epawk -X 'BEGIN {
        print <<-!
            #########################################
            #      generated by some author         #
            #        "ENVIRON["VAR"]"
            #########################################
        !
    }'
    BEGIN {
    print "#########################################"
    print "#      generated by some author         #"
    print "#        "ENVIRON["VAR"]""
    print "#########################################"
    }
    

    THE SCRIPT:

    #!/bin/bash
    # The above must be the first line of this script as bash or zsh is
    # required for the shell array reference syntax used in this script.
    
    ##########################################################
    # Extended Print AWK
    #
    # Allows printing of pre-formatted blocks of multi-line text in awk scripts.
    #
    # Before invoking the tool, do the following IN ORDER:
    #
    # 1) Start each block of pre-formatted text in your script with
    #       print << TERMINATOR
    #    on it's own line and end it with 
    #   TERMINATOR
    #    on it's own line. TERMINATOR can be any sequence of non-blank characters
    #    you like. Spaces are allowed around the symbols but are not required.
    #    If << is followed by -, e.g.:
    #       print <<- TERMINATOR
    #    then all leading tabs are removed from the block of pre-formatted
    #    text (just like shell here documents), if it's followed by + instead, e.g.:
    #       print <<+ TERMINATOR
    #    then however many leading tabs are common across all non-blank lines
    #    in the current pre-formatted block are removed.
    #    If << is followed by =, e.g.
    #       print <<= TERMINATOR
    #    then whatever leading white space (tabs or blanks) occurs before the
    #    "print" command will be removed from all non-blank lines in
    #    the current pre-formatted block.
    #    By default no leading spaces are removed. Anything you place after
    #    the TERMINATOR will be reproduced as-is after every line in the
    #    post-processed script, so this for example:
    #   print << HERE |"cat>&2"
    #       foo
    #   HERE
    #    would cause "foo" to be printed to stderr.
    #
    # 2) Within each block of pre-formatted text only:
    #   a) Put a backslash character before every backslash (\ -> \\).
    #   b) Put a backslash character before every double quote (" -> \").
    #   c) Enclose awk variables in double quotes without leading
    #      backslashes (awkVar -> "awkVar").
    #   d) Enclose awk record and field references ($0, $1, $2, etc.)
    #      in double quotes without leading backslashes ($1 -> "$1").
    #
    # 3) If the script is specified on the command line instead of via
    #    "-f script" then replace all single quote characters (') in or out
    #    of the pre-formatted blocks with their ANSI octal escape sequence (\047)
    #    or the sequence '\'' (tick backslash tick tick). This is normal and is
    #    required because command-line awk scripts cannot contain single quote
    #    characters as those delimit the script. Do not use hex \x27, see
    #    http://awk.freeshell.org/PrintASingleQuote.
    #
    # Then just use it like you would gawk with the small caveat that only
    # "-W 

    USAGE EXAMPLES:

    $ cat data.txt
    abc def"ghi
    

    .

    #######
    $ cat script.awk
    {
        awkVar="bar" 
    
        print "----------------"
    
        print << HERE
        backslash: \\
    
            quoted text: \"text\"
    
        single quote as ANSI sequence: \047
    
        literal single quote (ONLY works when script is in a file): '
    
        awk variable: "awkVar"
    
        awk field: "$2"
        HERE
    
        print "----------------"
    
        print <<-!
            backslash: \\
    
                quoted text: \"text\"
    
            single quote as ANSI sequence: \047
    
            literal single quote (ONLY works when script is in a file): '
    
            awk variable: "awkVar"
    
            awk field: "$2"
        !
    
        print "----------------"
    
        print <<+           whatever
            backslash: \\
    
        quoted text: \"text\"
    
            single quote as ANSI sequence: \047
    
            literal single quote (ONLY works when script is in a file): '
    
            awk variable: "awkVar"
    
            awk field: "$2"
        whatever
    
        print "----------------"
    }
    

    .

    $ epawk -f script.awk data.txt
    ----------------
        backslash: \
    
            quoted text: "text"
    
        single quote as ANSI sequence: '
    
        literal single quote (ONLY works when script is in a file): '
    
        awk variable: bar
    
        awk field: def"ghi
    ----------------
    backslash: \
    
        quoted text: "text"
    
    single quote as ANSI sequence: '
    
    literal single quote (ONLY works when script is in a file): '
    
    awk variable: bar
    
    awk field: def"ghi
    ----------------
        backslash: \
    
    quoted text: "text"
    
        single quote as ANSI sequence: '
    
        literal single quote (ONLY works when script is in a file): '
    
        awk variable: bar
    
        awk field: def"ghi
    ----------------
    

    .

    $ epawk -F\" '{
    print <

    .

    epawk -F\" '{
    print <

    .

    $ epawk -F\" '{
    print <

    .

    $ epawk -X 'BEGIN{
    print <

    .

    $ cat file
    a
    b
    c
    

    .

    $ epawk '{
        print <<+! |"cat>o2"
            numLines="NR"
                    numFields="NF", $0="$0", $1="$1"
        !
    }' file
    

    .

    $ cat o2
    numLines=1
            numFields=1, $0=a, $1=a
    numLines=2
            numFields=1, $0=b, $1=b
    numLines=3
            numFields=1, $0=c, $1=c
    

    .

    $ epawk 'BEGIN{
    
        cmd = "sort"
        print <<+! |& cmd
            d
            b
            a
            c
        !
        close(cmd, "to")
    
        while ( (cmd |& getline line) > 0 ) {
            print "got:", line
        }
        close(cmd)
    
    }' file
    got: a
    got: b
    got: c
    got: d
    

提交回复
热议问题