Как сделать обратное соответствие регулярному выражению [отрицание регулярного выражения] в Swift? - PullRequest
2 голосов
/ 12 мая 2019

Есть ли способ сделать обратное regular expression сопоставление и извлечь несоответствующую строку как возвращаемое значение в iOS Swift?

Скажем,

Входная строка: "232#$%4lion"

Шаблон регулярного выражения: "[a-z]{4}"

Нормальное совпадение Вывод: "lion"

Вывод обратного соответствия: "232#$%4" (ожидаемый результат)

Ниже приведен обычный код быстрого соответствия регулярному выражению.

func regexMatch() {

    let str = "232#$%4lion"

    let regex = try! NSRegularExpression(pattern: "[a-z]{4}", options: .caseInsensitive)
    let firstMatch = regex.firstMatch(in: str, options: .reportProgress, range: NSMakeRange(0, str.count))
    guard let matches = firstMatch else {
        print("No Match")
        return
    }

    if matches.numberOfRanges > 0 {
        let outputRange = matches.range(at: 0)
        let startIndex = str.index(str.startIndex, offsetBy: outputRange.lowerBound)
        let endIndex = str.index(str.startIndex, offsetBy: outputRange.upperBound)
        print("Matched String: \(str[startIndex..<endIndex])")
    }
}

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

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

Ответы [ 3 ]

1 голос
/ 13 мая 2019

Вы можете использовать свое регулярное выражение для удаления (заменить пустой строкой) найденные совпадения:

let result = str.replacingOccurrences(of: "[a-z]{4}", with: "", options: .regularExpression)

Свифт тест:

let str = "232#$%4lion"
let result = str.replacingOccurrences(of: "[a-z]{4}", with: "", options: .regularExpression)
print(result) 

Вывод: 232#$%4.

1 голос
/ 12 мая 2019

Либо используйте этот шаблон, однако он не инвертирует {4}, потому что он не предсказуем

"[^a-z]+"

или создайте новую изменяемую строку из str и удалите найденный диапазон

func invertedRegexMatch() {

    let str = "232#$%4lion"

    let regex = try! NSRegularExpression(pattern: "[a-z]{4}", options: .caseInsensitive)
    let firstMatch = regex.firstMatch(in: str, options: .reportProgress, range: NSRange(str.startIndex..., in: str))
    guard let matches = firstMatch else {
        print("No Match")
        return
    }

    if matches.numberOfRanges > 0 {
        let outputRange = Range(matches.range(at: 0), in: str)!
        var invertedString = str
        invertedString.removeSubrange(outputRange)
        print("Matched String: \(invertedString)")
    }
}

Примечание. Используйте всегда выделенный API для создания NSRange из Range<String.Index> и наоборот

Но если вы просто хотите удалить все буквы, есть гораздо более простой способ

var str = "232#$%4lion"
str.removeAll{$0.isLetter}
0 голосов
/ 12 мая 2019

Для этого не нужно использовать регулярное выражение. Вы можете просто использовать фильтр. RangeReplaceableCollection имеет метод экземпляра filter , который возвращает Self, String соответствует RangeReplaceableCollection, поэтому фильтр при использовании с String возвращает еще один String. Вы можете объединить его с новым Character свойством isLetter (Swift5) и создать предикат, отменяющий это свойство.


let str = "232#$%4lion"
let result = str.filter { !$0.isLetter }
print(result)   // "232#$%4"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...