命令行:在模板文件中的给定点插入unix命令的输出

时间:2014-05-12 15:12:09

标签: templates unix command-line awk sed

我正在寻找一个单行代码,用模板的base64字符串替换模板文件中的匹配字符串。所以在以下模板文件中:

# config.template.yaml

is_real: "yes"
project_base64: {base64_string}
file_name: "project.tgz"

以单行替换{base64_string},输出为base64 -w0 project.tgz

我尝试使用sed如下:

sed s/{base64_string}/`base64 -w0 project.tgz`/ config.template.yaml > config.yaml

如果project.tgz很小,这个工作正常,但实际上是几兆字节,我收到错误:

bash: /bin/sed: Argument list too long

4 个答案:

答案 0 :(得分:1)

$ cat file
is_real: "yes"
project_base64: {base64_string}
file_name: "project.tgz"

$ awk -v b64="$(printf "hello\nworld\n")" '{gsub(/{base64_string}/, b64); print}' file
is_real: "yes"
project_base64: hello
world
file_name: "project.tgz"

printf "hello\nworld\n"替换为base64 -w0 project.tgz

答案 1 :(得分:0)

在使用<(command)的情况下,如果使用<(base64 -w0 project.tgz)将命令伪装成文件,则可以使用use awk将命令的输出存储在数组中。
接下来,在处理file2时可以写入数组。

awk 'NR==FNR {a[NR]=$0;next}
    /^project_base64:/ { printf "project_base64:";
                         for (i=1; i <= length(a); i++) { print a[i] };
                         next
                       }
    {print}' <(base64 -w0 project.tgz) config.template.yaml

当要插入的命令只有一行时,不需要循环即可插入数组。选项-w0允许进行以下简化:

awk 'NR==FNR {a[NR]=$0; next}
    /^project_base64:/ { print "project_base64:" a[1];
                         next
                       }
    {print}' <(base64 -w0 project.tgz) config.template.yaml

要使用sed时,请确保base64sed执行:

sed 's/{base64_string}/printf "%s" "&";base64 -w0 project.tgz/e' config.template.yaml 

答案 2 :(得分:0)

使用Perl,

$ cat config.template.yaml
is_real: "yes"
project_base64: {base64_string}
file_name: "project.tgz"

$  perl -pe ' s/\{base64_string\}/qx(base64 -w0 project.tgz)/ge if /project_base64/ ' config.template.yaml
is_real: "yes"
project_base64: MTIzCg==
file_name: "project.tgz"

答案 3 :(得分:-3)

我最终使用的解决方案是使用awk,因为没有人理解awk我认为我会在此处发布以防其他人遇到类似问题:

awk '{"base64 -w0 project.tgz"|getline b64; gsub("{base64_string}", b64); print}' config.template.yaml > config.yaml

解释

awk是一个非常复杂的命令行工具,它针对文件的每一行运行一个小程序。该程序包含在花括号中:awk '{<your program here>}' <filename>

我意识到gsub功能很快就成了我的解决方案。花费我最多时间的部分是研究如何将bash命令的输出传递给gsub。结果getline是我的解决方案。如果执行"<some bash command>"|getline <var_name>,它将以该变量名称存储命令输出的第一行。

那么上面这行代表config.template.yaml的每一行:

  • base64 -w0 project.tgz的输出保存在变量b64
  • 在该行上运行gsub({base64_string}, b64),将所有{base64_string}替换为base64 -w0 project.tgz
  • 的输出
  • 将输出打印到STDOUT

然后我将所有输出重定向到新文件config.yaml并瞧!