为什么'\x1B'.length === 1?\x与\u知识延伸

开发 前端
自己从0-1写一个正则难免会有许多边界情况考虑不周全,于是在chalk的README中找到了chalk/ansi-regex[3]这个库。

[[427162]]

背景

先讲一下背景,再说原因

大多数库都会在日志中使用chalk库为console的内容进行上色

被chalk处理后,其原本的内容会被‘\x1B...’所包裹

  1. console.log(chalk.blue('green')); 
  2. console.log([chalk.blue('green')]); 

图片

在开发vite-plugin-monitor[1]时,为了获取原始的日志内容(上色之前),需要将上色后的字符串还原

  1. \x1B[34mgreen\x1B[39m => green 

在使用正则处理内容的时候发现了一个问题

  1. '\x1B'.replace(/\\x/,'') // 结果?? 

通过.length查看其长度,结果就如标题所示

原因

反斜杠"\"通常标识转义字符,如\n(换行符),\t(制表符)

而\x就标识16进制,后面跟上两位16进制数

与此同时还有\u也是标识16进制,但其后面需跟上4位16进制数

因此这里的\x1B实际上就是一个字符

  1. '\x41' === 'A'   // true 
  2. 'A' === '\u0041' // true 

\x

\xhh匹配一个以两位十六进制数(\x00-\xFF)表示的字符

主要用于ASCII码[2]的表示

  1. '\x41' === ‘A’ 
  2. 'A' === String.fromCharCode(65) 
  3.  
  4. '\x61' === ‘a’ 
  5. 'a' === String.fromCharCode(97) 

\x后必须跟着两位16进制的字符,否则会报错,其中 A-F 不区分大小写

  1. '\x1' // Uncaught SyntaxError: Invalid hexadecimal escape sequence 
  2. '\xfg' // Uncaught SyntaxError: Invalid hexadecimal escape sequence 

\u

\uhhhh匹配一个以四位十六进制数(\u0000-\uFFFF)表示的 Unicode 字符。

在正则表达式中常见于匹配中文字符

  1. const r = /[\u4e00-\u9fa5]/ 
  2. r.test('中文') // true 
  3. r.test('English') // false 

常规字符与Unicode字符互转

str2Unicode

使用String.prototype.charCodeAt获取指定位置的 Unicode 码点(十进制表示)

使用String.prototype.toString将其转为十六进制字符,转为16进制字符不会自动补0

通过String.prototype.padStart进行补0

编写的通用处理方法如下

  1. function str2Unicode(str) { 
  2.     let s = '' 
  3.     for (const c of str) { 
  4.         s += `\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}` 
  5.     } 
  6.     return s 
  7.  
  8. str2Unicode('1a中文') // '\\u0031\\u0061\\u4e2d\\u6587' 

unicode2Str

通过正则/\\u[\da-f]{4}/g匹配出所有的unicode字符

  1. 使用Number将0x${matchStr}转换为10进制数
  2. 使用String.fromCodePoint将unicode码点转为字符
  3. 使用String.prototype.replace进行逐字符的转换
  1. function str2Unicode(str) { 
  2.     let s = '' 
  3.     for (const c of str) { 
  4.         s += `\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}` 
  5.     } 
  6.     return s 
  7.  
  8. str2Unicode('1a中文') // '\\u0031\\u0061\\u4e2d\\u6587' 

还原chalk处理后的字符串

自己从0-1写一个正则难免会有许多边界情况考虑不周全,于是在chalk的README中找到了chalk/ansi-regex[3]这个库

可以将色值相关的 ANSI转义码 匹配出来

  1. import ansiRegex from 'ansi-regex'
  2.  
  3. '\u001B[4mcake\u001B[0m'.match(ansiRegex()); 
  4. //=> ['\u001B[4m''\u001B[0m'
  5.  
  6. '\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true})); 
  7. //=> ['\u001B[4m'

编写一下处理方法

  1. function resetChalkStr(str) { 
  2.     return str.replace(ansiRegex(), ''

测试

  1. console.log(chalk.green('green'), chalk.greenBright('greenBright')); 
  2.  
  3. console.log([chalk.green('green'), chalk.greenBright('greenBright')]); 
  4.  
  5. console.log(resetChalkStr(`${chalk.green('green')} ${chalk.greenBright('greenBright')}`)); 

总结

重拾了一下\x与\u相关的内容,突然额外想到一个点,使用\u去做字符串的加解密(下来再捋一捋)

解决了一个chalk相关的问题“还原终端中的彩色内容”

参考资料

[1]vite-plugin-monitor: https://github.com/ATQQ/vite-plugin-monitor

[2]ASCII码: https://tool.oschina.net/commons?type=4

[3]chalk/ansi-regex: https://github.com/chalk/ansi-regex

 

责任编辑:武晓燕 来源: 粥里有勺糖
相关推荐

2012-06-21 14:26:52

笔记本评测

2010-06-10 12:37:05

UML2.0

2022-11-02 07:39:53

CPU计算机C 语言

2017-08-03 10:38:32

HADOOP1.XHDFSHadoop

2024-02-20 22:13:49

SQL语句编程

2014-03-24 10:49:20

诺基亚UI京东

2011-12-18 21:35:59

笔记本评测

2021-11-15 06:56:45

MyBatis开发项目

2016-08-05 17:08:10

PythonWebpackAngular

2014-07-11 09:11:36

IBMsystem x联想

2015-01-06 11:13:21

CES2015264核Tegra X苹果A8X

2011-08-21 12:52:44

笔记本评测

2014-05-09 11:23:29

iOS移动互联网

2013-10-30 10:47:32

2012-02-13 14:56:18

三星笔记本

2011-04-25 15:29:00

联想ThinkPad

2012-08-09 12:05:05

笔记本

2012-10-11 15:45:24

MacBook碳纤维

2009-04-08 08:44:40

Windows Mob移动OS微软

2011-06-20 11:39:39

笔记本评测
点赞
收藏

51CTO技术栈公众号