#javascript #html #node.js #regex
#javascript #HTML #node.js #регулярное выражение
Вопрос:
Я использую Nodejs, чтобы проверить, есть ли какие-либо ошибки / предупреждения / уведомления, сгенерированные php в html-файле.
Первое, что я делаю, это фиксирую эти ошибки, используя это регулярное выражение в теге body:
const warningAndError = /(?:(?:.*n){0,0}).*?<b>(Warning|Error|Notice)</b>.*(?:(?:n.*))/gm;
Это вернет список, подобный этому :
["Error: Here goes the err message on line 571",
"Warning: Here goes the warn message on line 700"]
Что я хочу сделать дальше, так это создать такой массив :
[chalk.red.bold("Error: ") "Here goes the err message on line 571",
chalk.yellow.bold("Warning: ") "Here goes the warn message on line 700"]
Итак, мой код выглядит так:
const warningAndError = /(?:(?:.*n){0,0}).*?<b>(Warning|Error|Notice)</b>.*(?:(?:n.*){0,0})/gm;
const errList = [];
(body.match(warningAndError) || []).forEach((err) => {
let strippedString = err.replace(/(<([^>] )>)/gi, "");
if (strippedString.startsWith("Error:")) {
errList.push(
chalk.red.bold("Error: ") strippedString.replace("Error:", "").trim()
);
}
if (strippedString.startsWith("Warning:")) {
errList.push(
chalk.yellow.bold("Warning: ") strippedString.replace("Warning:", "").trim()
);
}
if (strippedString.startsWith("Notice:")) {
errList.push(
chalk.green.bold("Notice: ") strippedString.replace("Notice:", "").trim()
);
}
});
Проблема, с которой я сталкиваюсь, заключается в том, что это не чисто, поэтому мне было интересно, есть ли более чистый способ сделать это, и другое дело, что для выполнения требуется много времени, более 2 секунд.
Если это поможет, вот как ошибки выглядят на HTML-странице:
<br />
<b>Error</b>: Here goes the err message on line <b>571</b><br />
<br />
<b>Warning</b>: Here goes the warn message on line <b>700</b><br />
Заранее спасибо.
Комментарии:
1. Что
{0,0}
предполагается делать?2. @xehpuk если я не сделаю первое
{0,0}
, это вернет мне<br />
so, чтобы не захватывать строку перед строкой ошибки3.
x{0,0}
означает «повторить x ноль раз», так что это то же самое, что и пустая строка. Ваше текущее регулярное выражение может быть упрощено до/.*?<b>(Warning|Error|Notice)</b>.*/gm
.
Ответ №1:
Использование RegExp.prototype.exec(String)
должно сделать свое дело:
const levels = {
Error: 'red',
Warning: 'yellow',
Notice: 'green'
}
const regex = new RegExp(`<b>(${Object.keys(levels).join('|')})</b>: ([^<]*)<b>([^<]*)`, 'g')
function chalkify(html) {
const matches = []
let match
while ((match = regex.exec(html)) !== null) {
const [ , level, message, line ] = match
matches.push(chalk[levels[level]].bold(`${level}: `) message line)
}
regex.lastIndex = 0 // reset for next invocation
return matches
}
// "Polyfill" and test in the browser:
const chalk = {
red: { bold: _ => `<font color="red"><b>${_}</b></font>` },
yellow: { bold: _ => `<font color="yellow"><b>${_}</b></font>` },
green: { bold: _ => `<font color="green"><b>${_}</b></font>` }
}
document.body.innerHTML = chalkify(document.body.innerHTML).join('<br>')
<br />
<b>Error</b>: Here goes the err message on line <b>571</b><br />
<br />
<b>Warning</b>: Here goes the warn message on line <b>700</b><br />
Вы также можете использовать String.prototype.matchAll(RegExp)
, если вы хотя бы на Node.js 12.