為什么'\x1B'.length===1?\x與\u知識延伸


背景

先講一下背景,再說原因

大多數庫都會在日志中使用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

  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'

unicode2Str

  1. 通過正則/\\u[\da-f]{4}/g匹配出所有的unicode字符
  2. 使用Number0x${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中文

還原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相關的問題“還原終端中的彩色內容”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM