笔记:

笔记:

我有一个 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

还有一个 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)
}

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

答案1

您不需要“此处文档”。只需将整个 awk 程序(正确引用,以便 shell 无法识别其中的所有引号和元字符,并且换行符和其他空格不会导致 shell 将其拆分为多个参数)作为第一个命令行参数,而不使用 的awk选项-f。如果没有-f,第一个命令行参数就是要运行的程序。 手册awk页是你的朋友。

答案2

笔记:

自消耗脚本第二个代码示例中的模式可用于读取文件的任何内容。不要被 OP 的使用所分散注意力awk

回答:

你要求的是 heredoc。在这种情况下使用起来很棘手,但我喜欢 heredoc,所以我将向你展示如何做到这一点。你必须结合一个甚至鲜为人知的 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

这就是你想要的答案。现在,我要采用我称之为自耗脚本模式的方法。

#!/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

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

尽情抨击吧!欢迎随时访问 freenode 上的 #bash,获取更快速的答案。

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

答案3

带有引号限制字符串的 here-document 应该可以工作(参见此处文档例 19-7)。

例子

AWK_CODE=$(cat << 'HereDoc'
  BEGIN {FS="\t"}
  {print $0}
  HereDoc
)
awk "${AWK_CODE}" myfile.txt

相关内容