Parse output of spawned node.js child process line by line

后端 未结 6 1803
旧巷少年郎
旧巷少年郎 2020-12-07 21:05

I have a PhantomJS/CasperJS script which I\'m running from within a node.js script using process.spawn(). Since CasperJS doesn\'t support require()

相关标签:
6条回答
  • 2020-12-07 21:41

    You can give this a try. It will ignore any empty lines or empty new line breaks.

    cspr.stdout.on('data', (data) => {
        data = data.toString().split(/(\r?\n)/g);
        data.forEach((item, index) => {
            if (data[index] !== '\n' && data[index] !== '') {
                console.log(data[index]);
            }
        });
    });
    
    0 讨论(0)
  • 2020-12-07 21:42

    Adding to maerics' answer, which does not deal properly with cases where only part of a line is fed in a data dump (theirs will give you the first part and the second part of the line individually, as two separate lines.)

    var _breakOffFirstLine = /\r?\n/
    function filterStdoutDataDumpsToTextLines(callback){ //returns a function that takes chunks of stdin data, aggregates it, and passes lines one by one through to callback, all as soon as it gets them.
        var acc = ''
        return function(data){
            var splitted = data.toString().split(_breakOffFirstLine)
            var inTactLines = splitted.slice(0, splitted.length-1)
            var inTactLines[0] = acc+inTactLines[0] //if there was a partial, unended line in the previous dump, it is completed by the first section.
            acc = splitted[splitted.length-1] //if there is a partial, unended line in this dump, store it to be completed by the next (we assume there will be a terminating newline at some point. This is, generally, a safe assumption.)
            for(var i=0; i<inTactLines.length; ++i){
                callback(inTactLines[i])
            }
        }
    }
    

    usage:

    process.stdout.on('data', filterStdoutDataDumpsToTextLines(function(line){
        //each time this inner function is called, you will be getting a single, complete line of the stdout ^^
    }) )
    
    0 讨论(0)
  • 2020-12-07 21:44

    I've actually written a Node library for exactly this purpose, it's called stream-splitter and you can find it on Github: samcday/stream-splitter.

    The library provides a special Stream you can pipe your casper stdout into, along with a delimiter (in your case, \n), and it will emit neat token events, one for each line it has split out from the input Stream. The internal implementation for this is very simple, and delegates most of the magic to substack/node-buffers which means there's no unnecessary Buffer allocations/copies.

    0 讨论(0)
  • 2020-12-07 21:45

    I found a nicer way to do this with just pure node, which seems to work well:

    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 */)
    
    
    0 讨论(0)
  • 2020-12-07 21:58

    Old stuff but still useful...

    I have made a custom stream Transform subclass for this purpose.

    See https://stackoverflow.com/a/59400367/4861714

    0 讨论(0)
  • 2020-12-07 22:06

    Try this:

    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.
      }
    });
    

    Note that the "data" event might not necessarily break evenly between lines of output, so a single line might span multiple data events.

    0 讨论(0)
提交回复
热议问题