Я пытаюсь заменить двойные кавычки фигурными кавычками, за исключением случаев, когда текст обернут в определенные теги, такие как [quote] и [code].
Пример ввода
[quote="Name"][b]Alice[/b] said, "Hello world!"[/quote]
<p>"Why no goodbye?" replied [b]Bob[/b]. "It's always Hello!"</p>
Ожидаемый результат
[quote="Name"][b]Alice[/b] said, "Hello world!"[/quote]
<p>“Why no goodbye?” replied [b]Bob[/b]. “It's always Hello!”</p>
Я понял, как элегантно достичь того, что я хочу в PHP, используя (*SKIP)(*F)
, однако мой код будет выполняться в javascript,и решение javascript далеко не идеальное.
Прямо сейчас я разбиваю строку на эти теги, запускаю замену, затем соединяю строку:
var o = 3;
a = a
.split(/(\[(?<first>(?:icode|quote|code))[^\]]*?\](?:[\s]*?.)*?[\s]*?\[\/(?:\k<first>)\])/i)
.map(function(x,i) {
if (i == o-1 && x) {
x = '';
}
else if (i == o && x)
{
x = x.replace(/(?![^<]*>|[^\[]*\])"([^"]*?)"/gi, '“$1”')
o = o+3;
}
return x;
}).join('');
JavascriptРаспределение регулярных выражений
- Внутри
split()
: (\[(?<first>icode|quote|code)[^\]]*?\](?:.)*?\[\/(\k<first>)\])
- фиксирует шаблон в скобках: \[(?<first>quote|code|icode)[^\]]*?\]
- [quote]
,[code]
или [icode]
открывающий тег с такими параметрами или без них, как =html
, например, [code=html]
(?:[\s]*?.)*?
- любые 0+ (как можно меньше) вхождений любого символа (* 1039)*), перед или без пробела, поэтому он не прерывается, если за открывающим тегом следует разрыв строки [\s]*?
- 0+ пробелаs \[\/(\k<first>)\]
- [\quote]
, [\code]
или [\icode]
закрывающие теги.Соответствует тексту, захваченному в группе (?<first>)
.Например: если это цитата открывающий тег, это будет цитата закрывающий тег
- Внутри
replace()
: (?![^<]*>|[^\[]*\])"([^"]*?)"
- захватывает текст в двойных кавычках: (?![^<]*>|[^\[]*\])
- отрицательный прогноз, ищет символы (которые не являются <
или [
), за которыми следует либо>
или ]
и отбрасывает их, поэтому ничего не будет совпадать с внутри тегов bbcode и html.Например: [spoiler="Name"]
или <span style="color: #24c4f9">
.Обратите внимание, что совпадения в тегах в тегах остаются без изменений. "
- буквально открывающийся символ двойных кавычек. ([^"]*?)
- любой символ 0+, кроме двойных кавычек. "
- буквальный символ двойных кавычек.
SPLIT () REGEX DEMO: https://regex101.com/r/Ugy3GG/1
Это ужасно, потому что замена выполняется несколько раз.
Между тем, тот же результат может быть достигнут с помощью одного регулярного выражения PHP.Регулярное выражение, которое я написал, было основано на шаблоне соответствия регулярному выражению, которого нет в теге bbcode .
(\[(?<first>quote|code|icode)[^\]]*?\](?:[\s]*?.)*?[\s]*?\[\/(\k<first>)\])(*SKIP)(*F)|(?![^<]*>|[^\[]*\])"([^"]*?)"
Разбивка PHP Regex
(\[(?<first>quote|code|icode)[^\]]*?\](?:[\s]*?.)*?[\s]*?\[\/(\k<first>)\])(*SKIP)(*F)
- совпадает с шаблоном внутри круглых скобок, как javascript split()
выше, затем (*SKIP)(*F)
заставляет механизм регулярных выражений опускать сопоставленный текст. |
- или (?![^<]*>|[^\[]*\])"([^"]*?)"
- захватывает текст внутри двойных кавычек таким же образом, как javascript replace()
делает
PHP DEMO: https://regex101.com/r/fB0lyI/1
Красота этого регулярного выраженияв том, что его нужно запускать только один раз.Нет разделения и объединения строк.Есть ли способ реализовать это в javascript?