node子进程返回数据带ANSI编码处理

2020-03-08

node子进程返回数据带ANSI编码

什么是ANSI?

这里得说明下ANSI在终端内的作用,ANSI转义序列是一种带内信号的转义序列标准,用于控制视频文本终端上的光标位置、颜色和其他选项。在文本中嵌入确定的字节序列,大部分以ESC转义字符和”[“字符开始,终端会把这些字节序列解释为相应的指令,而不是普通的字符编码。

就是说node输出给我们的字符串本来是要在终端内展示的,而且这里是带格式的,例如错误的标红,换行,清屏等等。下面就是带ANSI的字符串:

这里有用的信息其实只有
File “test.py”, line 2
pythonEditor.vue?aa11:652
SyntaxError: invalid syntax
里有一些奇怪字符·[2等等,这些就是ASNI的控制字符

这里的点就是ESC的意思,其中我发现有一个是ESC]的奇怪字符,这里的中括号和其它事反的,通过终端发现ESC]后面的字符到下个控制命令之间的字符都会被忽略。就是“C:\Users\admin\AppData\Local\Programs\codesprite-test\resources\app\dist\electron\static\Python3\python.exe”这段是不需要的。
知道了这些我们就可以进行处理了,先找到获取ANSI的正则。

const ansiRegex = ({onlyFirst = false} = {}) => {
  const pattern = [
    '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
    '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
  ].join('|');
  return new RegExp(pattern, onlyFirst ? undefined : 'g');
}

通过正则可以将字符内所有ANSI字符匹配出来,然后将其删除,再特殊处理ESC]后面的字符串

function filter (text) {
  const arr = text.match(ansiRegex())
  arr.forEach((ele, idx) => {
    if (ele.includes(']')) {
      const _idx = text.indexOf(ele)
      if (idx !== arr.length - 1) {
        const next = arr[idx + 1]
        const _idx2 = text.indexOf(next) + next.length
        const as=text.slice(_idx, _idx2)
        text = text.replace(as, '')
      } else {
        const as = text.slice(_idx, text.length - 1)
        text = text.replace(as, '')
      }
    }
    text = text.replace(ele, '')
  })
  return text
}

这个就是简单的处理ansi字符的方法了。

评论(1条):

  • 狗子

    路人甲 2020-03-08 09:51

    emmmmm