粥里有勺糖

vuePress-theme-reco 粥里有勺糖    2018 - 2023
粥里有勺糖 粥里有勺糖

Choose mode

  • dark
  • auto
  • light
关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
author-avatar

粥里有勺糖

285

文章

40

标签

关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
  • devlearn

    • 开发教程
    • 实践:利用ArrayBuffer实现预览指定目录下的所有文件的内容
    • 在linux-deepin上使用deepin-wine5完美运行腾讯会议/QQ/微信等此类应用
    • eslint插件开发教程
    • ServerLess之云函数实践-天气API
    • 移动端阻止弹窗下层页面被滑动
    • 小技巧:for of中获取index
    • Git常用的一些基本操作
    • 向页面注入js实现为图片和文字元素添加透明蒙层
    • 实践:使用jsencrypt配合axios实现非对称加密传输的数据
    • 封装dotenv库实现类似Vite加载环境变量的行为
    • 30行代码实现合并指定目录下的所有文件的内容
    • 马上中秋了,把鼠标指针变为小玉兔
    • Node中require与fs.readFile读取JSON文件的对比
    • 使用免费的七牛云OSS(10G)搭建个人的在线图床
    • 分享封装的一些七牛云OSS操作方法
    • 本地配置SSH免密远程登录服务器
    • 工具方法汇总
    • 腾讯云Serverless实践-Node.js服务部署
    • 腾讯云Serverless实践-静态网站托管
    • 为什么'\x1B'.length === 1?\x与\u知识延伸
    • Vite插件开发纪实:vite-plugin-monitor(上)
    • Vite插件开发纪实:vite-plugin-monitor(中)
    • Vite插件开发纪实:vite-plugin-monitor(下)
    • 解决Vite-React项目中js使用jsx语法报错的问题
    • webpack 项目接入Vite的通用方案介绍
    • webpack 项目接入Vite的通用方案介绍-草稿
    • 优雅的处理挂载window上的函数可能不存在的情况
    • Mac上抓包秒通关羊了个羊

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

vuePress-theme-reco 粥里有勺糖    2018 - 2023

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

粥里有勺糖 2021-10-04 技术笔记技术教程

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

# 背景

先讲一下背景,再说原因

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

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

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

图片

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

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

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

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

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

图片

# 原因

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

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

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

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

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

# \x

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

主要用于ASCII码 (opens new window)的表示

'\x41' === ‘A’
'A' === String.fromCharCode(65)

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

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

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

# \u

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

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

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

# 常规字符与Unicode字符互转

# str2Unicode

  1. 使用String.prototype.charCodeAt获取指定位置的 Unicode 码点(十进制表示)
  2. 使用String.prototype.toString将其转为十六进制字符,转为16进制字符不会自动补0
  3. 通过String.prototype.padStart进行补0

编写的通用处理方法如下

function str2Unicode(str) {
    let s = ''
    for (const c of str) {
        s += `\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`
    }
    return s
}

str2Unicode('1a中文') // '\\u0031\\u0061\\u4e2d\\u6587'
1
2
3
4
5
6
7
8
9

# unicode2Str

  1. 通过正则/\\u[\da-f]{4}/g匹配出所有的unicode字符
  2. 使用Number将0x${matchStr}转换为10进制数
  3. 使用String.fromCodePoint将unicode码点转为字符
  4. 使用String.prototype.replace进行逐字符的转换
function unicode2Str(str) {
    const unicodeList = str.match(/\\u[\da-f]{4}/g) || []
    return unicodeList.reduce((pre, u) => {
        return pre.replace(u, String.fromCodePoint(Number(`0x${u.slice(2)}`)))
    }, str)
}

unicode2Str('1\\u0061\\u4e2d文') // 1a中文
1
2
3
4
5
6
7
8

# 还原chalk处理后的字符串

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

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

import ansiRegex from 'ansi-regex';

'\u001B[4mcake\u001B[0m'.match(ansiRegex());
//=> ['\u001B[4m', '\u001B[0m']

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

编写一下处理方法

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

测试

console.log(chalk.green('green'), chalk.greenBright('greenBright'));

console.log([chalk.green('green'), chalk.greenBright('greenBright')]);

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

图片

# 总结

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

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

Edit this page (opens new window)
Last Updated: 2022/5/15 12:46:34