使用awk作为简单模板引擎,如何修改getline最后一行的输出

使用awk作为简单模板引擎,如何修改getline最后一行的输出

我正在尝试使用 awk 来做一些简单的模板。我有一个“模板”文件,如下所示:

{
  "Thing": {
    "Code": [
      #include_code
    ]
  }
}

我使用下面的 awk 程序将该#include_code行替换为文件的内容,但每行都用双引号括起来并以逗号结尾(以在输出中生成有效的 JSON 列表)。

#!/usr/bin/awk -f

! /#include_code/ { print $0 }

/#include_code/ {
  while(( getline line<"test_file.js") > 0 ) {
    print "\"" line "\","
  }
}

哪里test_file.js

index.handler = (event, context) => {
    return true;
}

我的问题是我不想打印最后一个逗号,但我不确定如何防止打印该逗号。明确地说,这是输出:

{
  "Thing": {
    "Code": [
"index.handler = (event, context) => {",
"    return true;",
"}", <--- I don't want this comma...
    ]
  }
}

虽然我想要一个使用 awk 执行此操作的答案(因为我正在尝试学习它)。我会很高兴得到一个答案,它向我指出了您建议我使用的不同的模板工具。

答案1

一种方法是计算脚本开头的行数。输出时,只有当你的行号与行数不匹配时,才在末尾输出一个逗号。解释了如何执行此操作这里

另一种方法是,在输出第一个条目时不打印逗号,而是打印一个随后的条目。这可以按如下方式完成:

 awk -F, '{if (!i)printf "\""$0"\"";else printf ",\n\""$0"\"";i=1}END{print ""}' a.in

这绝对干净得多。

还有第三种方法。代码

 if(getline == 0)

读取下一行,从而告诉您是否位于文件末尾。这样做比上面的方法更干净,但是会因有效读取文件两次而产生开销,因此除非第二种方法失败,否则我不会使用它(例如,我也必须以不同的方式处理倒数第二行) 。

答案2

这样做可能更容易:

sed 's/.*/"&"/;$!s/$/,/' test_file.js | sed '/#include_code/{
  r /dev/stdin
  d;}' template

(假设 只出现一次#include_code)。

使用awk,您可以这样做:

awk '
  /#include_code/ {
    sep = ""
    while((getline < "test_file.js") > 0) {
      printf "%s", sep "\"" $0 "\""
      sep = ",\n"
    }
    if (sep) print ""
    next
  }
  {print}' template

您还可以使用与sed上面类似的方法:

CODE='test_file.js' SED='sed '\''s/.*/"&"/;$!s/$/,/'\' "$CODE"' awk '
  /#include_code/{system(ENVIRON["SED"); next};{print}' template

相关内容