Вопросу пару месяцев, но я думаю, что этот ответ - ваш лучший выбор.Преобразование escape-последовательностей из необработанных строк очень выполнимо с ES6 String.fromcodepoint(<hex-value>)
.Я нахожусь в процессе написания пакета NPM, который имеет дело с этим точным сценарием.
Во-первых, вам нужно регулярное выражение, которое соответствует всем escape-последовательностям в вашей строке.Я использовал это как ссылку для всех разных.(Я использую для этого необработанную строку, чтобы избежать появления спама в обратном слэше)
let [single, ...hex] = String.raw`
\\[bfnrtv0'"\\]
\\x[a-fA-F0-9]{2}
(\\u[a-fA-F0-9]{4}){1,}
\\u\{([0-9a-fA-F]{1,})\}`
.split("\n").slice(1).map(cur => cur.trim());
let escapes = new RegExp(`(${[single].concat(hex).join("|")})`, "gm"),
// We need these for later when differentiating how we convert the different escapes.
uniES6 = new RegExp(`${hex.pop()}`);
single = new RegExp(`${single}`);
Теперь вы можете сопоставить все экранированные символы;зарезервированные одиночные символы, расширенный диапазон ASCII, шестнадцатеричные числа Unicode ES6 и суррогатные пары.(кроме восьмеричных, потому что они устарели, но вы всегда можете добавить их обратно).Следующим шагом является написание функции, которая может заменить кодовые точки соответствующими символами.Сначала переключаемая функция для синглов:
const singleEscape = seq =>
(() => ({
"\\b" : "\b",
"\\f" : "\f",
"\\n" : "\n",
"\\r" : "\r",
"\\t" : "\t",
"\\v" : "\v",
"\\0" : "\0",
"\\'" : "\'",
"\\\"" : "\"",
"\\\\" : "\\"
}[seq]))();
Затем мы можем положиться на ES6 fromcodepoint
, чтобы справиться с остальными, которые являются шестнадцатеричными.
const convertEscape = seq => {
if (single.test(seq))
return singleEscape(seq);
else if (uniES6.test(seq))
return String.fromCodePoint(`0x${seq.split("").slice(3, -1).join("")}`);
else
return String.fromCodePoint.apply(
String, seq.split("\\").slice(1).map(pt => `0x${pt.substr(1)}`)
);
}
Наконец, мы связываемвсе это вместе с помеченной литеральной функцией шаблона с именем normal
.Я не знаю, зачем вам необработанная строка, но здесь вы можете получить доступ к необработанной строке и поместить любую дополнительную логику, в то же время получая строку, в которой escape-последовательности правильно анализируются.
const normal = (strings, ...values) => strings.raw
.reduce((acc, cur, i) => acc += (values[i-1] || "") + cur, "")
.replace(escapes, match => convertEscape(match));