Я настоятельно рекомендую вместо этого использовать анализатор уценки.Они, вероятно, будут более точными и меньше страдают от крайних случаев, чем регулярные выражения.
При этом вы можете проанализировать его с помощью регулярных выражений.Однако ваш подход терпит неудачу из-за того, как вы обрабатываете токены.Вы назначаете токены уценки различным унифицированным токенам (что само по себе является ненужным преобразованием), а затем назначаете один и тот же токен двум различным закрывающим тегам.Это и цикл, вероятно, заставляют все теги заканчиваться как закрывающие теги.
Хранение токенов - неплохая идея, поэтому давайте начнем с этого.Создайте соединения между **
и b
и *
и i
.От ***
до bi
не требуется - в конце этого синтаксический анализ преобразует их по шагам и сначала преобразует ***content***
в <b>*content*</b>
, а затем преобразует его в <b><i>content</b></i>
.В этом случае я сопоставляю с помощью регулярных выражений, чтобы потом было проще:
val tokens = mapOf(
"\\*\\*" to "b", "\\*" to "i", "~~" to "s"
)
Само регулярное выражение более сложное:
Соответствие пустым не должно происходить, интервалы должны игнорироваться, иэто нужно сделать для двух разных типов.
В любом случае, у нас есть основное регулярное выражение:
val core = "(?<!\* )(?=\S)(.+?[*]*)(?<=\S)(?<! \*)"
Обратите внимание, что одно это не будет работать одно .Первая и последняя группы должны избегать синтаксического анализа *** something***
как допустимого, поскольку *
также является допустимым символом во внутреннем.
В этом случае я определил var string: String
в примере, но вы, конечно, можете заменить его на что-то другое.Это просто для мобильности.
var string = "***this*** **is** a ***test of* a markdown *regex* parsing system** that I really **hope *works* like it's supposed to**. " +
"And an ** invalid one **, and not to forget ~~the broken regex~~ the perfect regex"
for ((token, html) in tokens) { // if you don't know, Map entries can be unpacked like tuples. The token is for an instance **, and html is b
val modRegex = "$token$core$token".toRegex() // Construct the regex. This is why the format in the map is regex-style
string = string.replace(modRegex, "<$html>$1</$html>")//And finally, we replace it. The String templates ensure the right match, `$1` is the first capture group to avoid losing content
}
Ради демонстрации я также напечатал string
:
<b><i>this</i></b> <b>is</b> a <b><i>test of</i> a markdown <i>regex</i> parsing system</b> that I really <b>hope <i>works</i> like it's supposed to</b>. And an ** invalid one **, and not to forget <s>the broken regex</s> the perfect regex
this - это a тест уценка регулярное выражение система парсинга , что я действительно надеюсь работает как будто это должно было .И ** неверный **, и не забывать сломанное регулярное выражение идеальное регулярное выражение
Теперь регулярное выражение далеко от совершенства, особенно когда речь идет о уценке.Есть несколько крайних случаев и неправильная обработка, которая возникает из-за неправильной уценки.Вы не можете просто разместить случайные токены и интерпретировать их как действительную уценку.Таким образом, неправильно размещенные токены, скорее всего, приведут к неправильной обработке и синтаксическому анализу, поэтому я снова настоятельно рекомендую использовать анализатор уценки, а не регулярное выражение.
И хотя это можно распространить на другие токены, этоне работает со ссылками .()[]
требует смещения групп вокруг HTML для работы, и есть две соответствующие группы.($1)[$2]
-> <a href="$1">$2</a>
, и это снова игнорирует альтернативный текст в URL.
В любом случае, код в этом ответе все равно должен помочь вам в системе синтаксического анализа регулярных выражений, даже если она далека от совершенства.