Ошибка RegEx.IgnoreCase

Например, у меня есть небольшая функция, которая возвращает строку между двумя другими строками (например, между одинарными, двойными кавычками или даже простым тегом html).

        Dim exp As String = String.Format("{0}(.*?){1}", beginMarker, endMarker)

Теперь, если я передам «‹b›» для маркера начала и «‹/b›» для маркера конца и не укажу регистр RegEx.Ignore, он правильно вернет соответствующий нижний регистр ‹b›‹/b ›. Однако, как только я указываю IgnoreCase, он никогда не возвращается (при условии того же ввода). Вот пример функции (удалите RegexOptions.IgnoreCase, и она заработает). Кроме того, независимо от того, избегаю ли я вводимых маркеров, это не меняет вывод, единственная разница заключается в IgnoreCase:

Мой вопрос: что мне не хватает (я использовал простой пример, потому что на самом деле я не анализирую HTML с атрибутами)?

Ввод: beginMarker = "‹b›"
Ввод: endMarker = "‹/b›"
Ввод: searchText = "‹b›это тест‹/b›"
Ввод: beginMakers (не имеет значения, True или False)

Public Shared Function GetStringInBetween(beginMarker As String, endMarker As String, searchText As String, includeMarkers As Boolean) As List(Of String)
    beginMarker = RegularExpressions.Regex.Escape(beginMarker)
    endMarker = RegularExpressions.Regex.Escape(endMarker)
    Dim exp As String = String.Format("{0}(.*?){1}", beginMarker, endMarker)
    Dim regEx As New RegularExpressions.Regex(exp)
    Dim returnList As New List(Of String)

    For Each m As Match In regEx.Matches(searchText, 0, RegexOptions.IgnoreCase)
        If includeMarkers = True Then
            returnList.Add(m.Value)
        Else
            returnList.Add(m.Value.TrimStart(beginMarker.ToCharArray).TrimEnd(endMarker.ToCharArray))
        End If
    Next

    Return returnList
End Function

person b.pell    schedule 23.07.2012    source источник
comment
Невозможно надежно анализировать HTML-теги с помощью регулярных выражений. Убедитесь, что вы не зависите от этого поведения, или найдите другой способ сделать это.   -  person Wug    schedule 23.07.2012
comment
Я просто использовал полужирный тег для примера. Просто представьте, что два статических маркера похожи на одинарную кавычку. «Это тест» или «Это тест». Я предположил, что IgnoreCase позволит сопоставить оба из них, но когда я включил его, ни один из них не совпадал.   -  person b.pell    schedule 23.07.2012
comment
Вы правильно используете спички? и рассмотрим следующую ситуацию: <b><b></b>Something</b>   -  person Wug    schedule 23.07.2012
comment
Я этого не делал, но это хороший пример, подтверждающий вашу точку зрения. Меня действительно интересуют кавычки и двойные кавычки (где «Что-то» вернет пробел, а затем «Что-то», например, 2 совпадения). Мой вопрос все еще заключается в том, почему приведенный выше код VB/RegEx работает, когда IgnoreCase выключен... но теперь, когда он включен).   -  person b.pell    schedule 23.07.2012


Ответы (1)


Я бы не стал использовать имя класса .NET для имени переменной, так как это может запутать.

Это работает, и я изменил функции Trim, чтобы этот регистр игнорировался:

Imports System.Text.RegularExpressions

Module Module1

    Public Function GetStringInBetween(beginMarker As String, endMarker As String, searchText As String, includeMarkers As Boolean) As List(Of String)
        Dim exp As String = String.Format("{0}(.*?){1}", Regex.Escape(beginMarker), Regex.Escape(endMarker))
        Dim returnList As New List(Of String)

        For Each m As Match In Regex.Matches(searchText, exp, RegexOptions.IgnoreCase)
            If includeMarkers Then
                returnList.Add(m.Value)
            Else
                ' return the portion of the matched string without the markers
                returnList.Add(m.Value.Substring(beginMarker.Length, m.Value.Length - beginMarker.Length - endMarker.Length))
            End If
        Next

        Return returnList

    End Function

    Sub Main()
        ' include a \ to confirm the regex escaping 
        ' outputs: "hello, again"
        Console.WriteLine(String.Join(", ", GetStringInBetween("<x>", "</\x>", "<X>hello</\x> world <x>again</\x>", False).ToArray))
        Console.ReadLine()
    End Sub

End Module

Изменить: Ах да, используйте также Option Strict On. И нет перегрузки RegEx.Matches, которая принимает (String, Int32, String) в качестве параметров.

person Andrew Morton    schedule 23.07.2012
comment
Отлично ... это точно соответствует поведению, которое я видел (что было моей ошибкой, у меня не было строгой опции, и, похоже, это было смешивание и сопоставление перегрузок). - person b.pell; 23.07.2012