我有一个 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,获取更快速的答案。
答案3
带有引号限制字符串的 here-document 应该可以工作(参见此处文档例 19-7)。
例子
AWK_CODE=$(cat << 'HereDoc'
BEGIN {FS="\t"}
{print $0}
HereDoc
)
awk "${AWK_CODE}" myfile.txt