我正在尝试使用Node.js编写文件模板脚本。我有一个名为template.json
的JSON文件,它存储模板信息。我的脚本背后的想法是,如果我输入类似:
tmpl.js java Joe
它将执行以下操作:
touch Joe.java
template.json
以获取Java文件的模板Joe
Joe.java
emacsclient Joe.java
现在,我按如下方式编写了这个脚本:
#!/usr/local/bin/node --harmony
var templates = require('./config/template.json'),
args = process.argv;
if (args.length < 4) {
console.log("Not enough arguments!");
}
else {
var type = args[2],
name = args[3];
if (type in templates) {
var tmpl = templates[type],
contents = make_output(tmpl["format"],name),
file_name = name + tmpl["extension"],
command = "touch " + file_name + " && echo -e '" + contents +
"' &> " + file_name + " && emacsclient " + file_name;
invoke(command);
}
else {
console.log("No template for %s", type);
}
}
//Helpers
//Invokes comm with args in the terminal, returns all output
//Does not play nice with command redirection
function invoke(comm) {
var exec = require('child_process').exec,
child = exec(comm,
function (error, stdout, stderr) {
if (error !== null) {
console.log(stderr);
}
});
}
//If template is a format string, processes it with x as the
//replacement. Otherwise, just evaluates.
//Limited to one replacement at most.
function make_output(template, x) {
if(/.*\%s.*/i.test(template)) {
var util = require('util');
return util.format(template,x);
}
else {
return template;
}
}
基本上,它最终构建的命令类似于:
touch Joe.java && echo -e `bunch of template stuffs` &> Joe.java && emacsclient Joe.java
现在,我得到的问题是上面的命令依赖于输出重定向,我的invoke
命令没有很好地处理 - 具体来说,一切都在执行,但我得到一个空文件!有没有办法可以更改invoke
或我正在构建的被调用以避免此问题?
答案 0 :(得分:2)
问题是,节点child_process.exec
启动sh
,但您使用的是bash
特有的功能。 &>
在& >
中被解释为sh
(两个运算符:一个控制运算符和一个重定向运算符),echo -e
将使用sh
的内置实现echo
,不理解-e
。
可能可以解决上述问题,但像你一样使用shell是脆弱的。例如,如果您的模板包含单引号('
),则这些引号可能会干扰您在命令中使用的单引号。一种更健壮的方法是将代码的主要部分更改为使用fs.writeFileSync
而不是使用shell命令写入文件:
var templates = require('./config/template.json'),
fs = require("fs"),
args = process.argv;
if (args.length < 4) {
console.log("Not enough arguments!");
}
else {
var type = args[2],
name = args[3];
if (type in templates) {
var tmpl = templates[type],
contents = make_output(tmpl["format"],name),
file_name = name + tmpl["extension"],
command = "emacsclient " + file_name;
fs.writeFileSync(file_name, contents);
invoke(command);
}
else {
console.log("No template for %s", type);
}
}
您还希望修改make_output
以执行echo -e
为您完成的转换。