如何编写`awk here document`

kev*_*kev 1 awk

我有一个 bash 脚本:

#!/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
Run Code Online (Sandbox Code Playgroud)

还有一个 awk 脚本:

#!/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)
}
Run Code Online (Sandbox Code Playgroud)

如何将这两个脚本合二为一?

Bru*_*sky 7

笔记:

第二个代码示例中的自消费脚本模式可用于读取文件的任何内容。不要被 OP 使用awk.

回答:

你要的是一个heredoc。在这种情况下使用起来很棘手,但我喜欢 heredocs,所以我将向您展示如何去做。您必须合并一个鲜为人知的 bash 功能,使用 <() 进行进程替换

#!/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
Run Code Online (Sandbox Code Playgroud)

所以这就是你要的答案。现在,我将使用我所谓的自消费脚本模式来做这件事。

#!/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
Run Code Online (Sandbox Code Playgroud)

对我来说,这很容易理解,您可以通过增加分隔符将多个 AWK 或其他脚本放在一个文件中。

享受猛击!随时访问 freenode 上的 #bash 以获得更快的答案。

有关更多信息,请参阅http://tldp.org/LDP/abs/html/process-sub.html

  • 这就是黑魔法!!我的意思是,它很清楚,但它是如此聪明! (2认同)