背景
先講一下背景,再說原因
大多數庫都會在日誌中使用chalk
庫為console的內容進行上色
被chalk
處理後,其原本的內容會被‘\x1B...’所包裹
console.log(chalk.blue('green'));
console.log([chalk.blue('green')]);
在開發vite-plugin-monitor時,為了獲取原始的日誌內容(上色之前),需要將上色後的字串還原
\x1B[34mgreen\x1B[39m => green
在使用正則處理內容的時候發現了一個問題
'\x1B'.replace(/\\x/,'') // 結果??
通過.length
檢視其長度,結果就如標題所示
原因
反斜槓"\"
通常標識轉義字元,如\n(換行符)
,\t(製表符)
而\x
就標識16進位制,後面跟上兩位16進位制數
與此同時還有\u
也是標識16進位制,但其後面需跟上4位16進位制數
因此這裡的\x1B
實際上就是一個字元
'\x41' === 'A' // true
'A' === '\u0041' // true
\x
\xhh
匹配一個以兩位十六進位制數(\x00
-\xFF
)表示的字元
主要用於ASCII碼的表示
'\x41' === ‘A’
'A' === String.fromCharCode(65)
'\x61' === ‘a’
'a' === String.fromCharCode(97)
\x
後必須跟著兩位16進位制的字元,否則會報錯,其中 A
-F
不區分大小寫
'\x1' // Uncaught SyntaxError: Invalid hexadecimal escape sequence
'\xfg' // Uncaught SyntaxError: Invalid hexadecimal escape sequence
\u
\uhhhh
匹配一個以四位十六進位制數(\u0000
-\uFFFF
)表示的 Unicode 字元。
在正規表示式中常見於匹配中文字元
const r = /[\u4e00-\u9fa5]/
r.test('中文') // true
r.test('English') // false
常規字元與Unicode字元互轉
str2Unicode
- 使用
String.prototype.charCodeAt
獲取指定位置的 Unicode 碼點(十進位制表示) - 使用
String.prototype.toString
將其轉為十六進位制字元,轉為16進位制字元不會自動補0 - 通過
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'
unicode2Str
- 通過正則
/\\u[\da-f]{4}/g
匹配出所有的unicode字元 - 使用
Number
將0x${matchStr}
轉換為10進位制數 - 使用
String.fromCodePoint
將unicode碼點轉為字元 - 使用
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中文
還原chalk處理後的字串
自己從0-1寫一個正則難免會有許多邊界情況考慮不周全,於是在chalk的README中找到了chalk/ansi-regex這個庫
可以將色值相關的 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']
編寫一下處理方法
function resetChalkStr(str) {
return str.replace(ansiRegex(), '')
}
測試
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')}`));
總結
重拾了一下\x
與\u
相關的內容,突然額外想到一個點,使用\u去做字串的加解密(下來再捋一捋)
解決了一個chalk
相關的問題“還原終端中的彩色內容”