Неверный ответ функции - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть функция, которая форматирует входную строку в формат для строки html

For example, lorem ipsum *dolor sit amet* consectetur **adipiscing** elit.

Где

* is for <i>
** is for <b>

Итак, выходная строка может быть:

Lorem ipsum <i>dolor sit amet</i>, consectetur <b>adipiscing</b> elit.

Я написал эту функцию:

val input = "Lorem ipsum *dolor sit amet*, consectetur **adipiscing** elit."                                      

val tagMap = mapOf(                                                                                               
        '*' to "<i>",                                                                                             
        '♥' to "<b>",                                                                                             
        '♦' to "<s>"                                                                                              
)                                                                                                                 

val tagMapClose = mapOf(                                                                                          
        '*' to "</i>",                                                                                            
        '♥' to "</b>",                                                                                            
        '♦' to "</s>"                                                                                             
)                                                                                                                 

fun tagCheck(obj: String): String {                                                                               
    var str = Regex("""\*\*""").replace(obj, "♥")                                                                 
    str = Regex("""~~""").replace(str, "♦")                                                                       
    str = Regex("""\*\*\*""").replace(str, "♥*")                                                                  
    val charList = str.toList()                                                                                   
    var res = ""                                                                                                  
    val indexMap = mutableMapOf<Int, String>()                                                                    
    var ct = 0                                                                                                    

    for ((tag, define) in tagMap) {                                                                               
        val tagIndex = mutableListOf<Int>()                                                                       
        var status = true                                                                                         
        for (char in charList) if (char == tag) tagIndex.add(charList.indexOf(char))                              
        ct = if (tagIndex.size % 2 == 1) tagIndex.size                                                            
        else tagIndex.size + 1                                                                                    

         for (i in 0 until ct - 1) {                                                                               
           if (status) {                                                                                         
                indexMap[tagIndex[i]] = tagMap.getValue(tag)                                                      
                status = false                                                                                    
            }                                                                                                     
            else if (!status) {                                                                                   
                indexMap[tagIndex[i]] = tagMapClose.getValue(tag)                                                 
                status = true                                                                                     
            }                                                                                                     
        }                                                                                                         
                                                                        }                                                                                                             
for (item in charList) {                                                                                      
        res += if (indexMap.keys.contains(charList.indexOf(item))) indexMap[charList.indexOf(item)]               
        else item                                                                                                 
    }                                                                                                             
    return res                                                                                                    
    }                                                                                                                 

Но в выводе я получаю это:

Lorem ipsum </i>dolor sit amet</i>, consectetur </b>adipiscing</b> elit.

Итак, функция не может проверять открытый или закрытый тег, она просто пишет толькозакрытые теги, что мне делать?

1 Ответ

0 голосов
/ 07 апреля 2019

Я настоятельно рекомендую вместо этого использовать анализатор уценки.Они, вероятно, будут более точными и меньше страдают от крайних случаев, чем регулярные выражения.

При этом вы можете проанализировать его с помощью регулярных выражений.Однако ваш подход терпит неудачу из-за того, как вы обрабатываете токены.Вы назначаете токены уценки различным унифицированным токенам (что само по себе является ненужным преобразованием), а затем назначаете один и тот же токен двум различным закрывающим тегам.Это и цикл, вероятно, заставляют все теги заканчиваться как закрывающие теги.

Хранение токенов - неплохая идея, поэтому давайте начнем с этого.Создайте соединения между ** и 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.

В любом случае, код в этом ответе все равно должен помочь вам в системе синтаксического анализа регулярных выражений, даже если она далека от совершенства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...