逐行解析生成的node.js子进程的输出

Jes*_*ton 19 node.js phantomjs

我有一个PhantomJS/CasperJS脚本,我正在使用node.js脚本运行process.spawn().由于CasperJS不支持require()模块,我试图从CasperJS打印命令stdout,然后从我的node.js脚本中读取它们spawn.stdout.on('data', function(data) {});,以便执行诸如将对象添加到redis/mongoose之类的事情(复杂,是的,但似乎比为此设置Web服务更简单...)CasperJS脚本执行一系列命令,并创建20个需要添加到我的数据库的屏幕截图.

但是,我无法弄清楚如何将data变量(a Buffer?)分解为行...我已经尝试将其转换为字符串然后进行替换,我已经尝试过spawn.stdout.setEncoding('utf8');但似乎没有任何工作......

这就是我现在所拥有的

var spawn = require('child_process').spawn;

var bin = "casperjs"
//googlelinks.js is the example given at http://casperjs.org/#quickstart
var args = ['scripts/googlelinks.js'];
var cspr = spawn(bin, args);

//cspr.stdout.setEncoding('utf8');
cspr.stdout.on('data', function (data) {
    var buff = new Buffer(data);
    console.log("foo: " + buff.toString('utf8'));
});

cspr.stderr.on('data', function (data) {
    data += '';
    console.log(data.replace("\n", "\nstderr: "));
});

cspr.on('exit', function (code) {
    console.log('child process exited with code ' + code);
    process.exit(code);
});
Run Code Online (Sandbox Code Playgroud)

https://gist.github.com/2131204

mae*_*ics 16

试试这个:

cspr.stdout.setEncoding('utf8');
cspr.stdout.on('data', function(data) {
  var str = data.toString(), lines = str.split(/(\r?\n)/g);
  for (var i=0; i<lines.length; i++) {
    // Process the line, noting it might be incomplete.
  }
});
Run Code Online (Sandbox Code Playgroud)

请注意,"data"事件可能不一定在输出行之间均匀分布,因此单行可能跨越多个数据事件.

  • @JesseFulton:`\ r``是正则表达式特殊字符```的可选项,所以这段代码应该适用于UNIX和Windows; 它使得正则表达式全局(`.../g`)在这里可能很关键.在示例代码中对"替换"的调用使用了一个纯字符串,该字符串被转换为非全局正则表达式,因此您可能只有两行而不是所有这些行. (2认同)

Sam*_*Day 12

我实际上是为了这个目的编写了一个Node库,它被称为流分割器,你可以在Github上找到它:samcday/stream-splitter.

该库提供了一个特殊的,Stream你可以将你的casper stdout连接到一个分隔符(在你的情况下,\n),它将发出整齐的token事件,每个事件从它从输入中分离出来Stream.对此的内部实现非常简单,并将大部分魔法委托给substack/node-buffers,这意味着没有不必要的Buffer分配/副本.


nyc*_*tef 8

我找到了一种更好的方法来使用纯节点来做到这一点,它似乎工作得很好:

const childProcess = require('child_process');
const readline = require('readline');

const cspr = childProcess.spawn(bin, args);

const rl = readline.createInterface({ input: cspr.stdout });
rl.on('line', line => /* handle line here */)

Run Code Online (Sandbox Code Playgroud)