Почему регулярное выражение сопоставляет слова, содержащие только буквы, тогда как оно должно сопоставлять слова, содержащие как буквы, так и цифры?

ФОН
Я хочу заменить слова, содержащие только буквы и цифры, а также букву и цифру, пробелами. Я использую VBA, как показано в примере ниже.

Предлагаемое решение смотрите здесь: https://stackoverflow.com/a/7684859

ВОПРОС
Почему регулярное выражение соответствует слову «WhyIsThisWordMatched», если оно не содержит цифр? И как можно исправить регулярное выражение, чтобы оно соответствовало только словам, содержащим и буквы, и цифры, и только буквы и цифры?

Public Sub TestMe()
    Dim Rx As Object
    Dim Txt As String

    Set Rx = CreateObject("VBScript.RegExp")
    Rx.Global = True
    Rx.Pattern = "(^|\s)(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)($|\s)"
    Txt = "WhyIsThisWordMatched XXX-111"
    Txt = Rx.Replace(Txt, " ")
    Debug.Print "Result: " & Txt
    ' Prints the string "  XXX-111"
End Sub
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Операции просмотра не используют символы, они просто подтверждают, возможно ли совпадение. Шаблон (?=.*[0-9]) гарантирует, что где-то впереди есть цифра, а (?=.*[a-zA-Z]) гарантирует, что где-то впереди есть буква, но не гарантирует, что обе буквы существуют в одном и том же слове.

Текущий шаблон (^|\s)(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)($|\s) соответствует любому слову из букв и цифр, которое следует за пробелом или началом строки и предшествует пробелу или концу строки, при условии, что где-то в строке есть цифра и буква (не обязательно одним и тем же словом).

Этот шаблон, вероятно, должен решить непосредственную проблему:

(^|\s)(?=\w*[0-9])(?=\w*[a-zA-Z])[a-zA-Z0-9]+($|\s)

Итак, ваш код будет выглядеть примерно так:

Public Sub TestMe()
    Dim Rx As Object
    Dim Txt As String

    Set Rx = CreateObject("VBScript.RegExp")
    Rx.Global = True
    Rx.Pattern = "(^|\s)(?=\w*[0-9])(?=\w*[a-zA-Z])[a-zA-Z0-9]+($|\s)"
    Txt = "WhyIsThisWordMatched XXX-111 abc123"
    Txt = Rx.Replace(Txt, " ")
    Debug.Print "Result: " & Txt
    ' Prints the string "WhyIsThisWordMatched XXX-111 "
End Sub

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

(?<!\S)(?=\S*[0-9])(?=\S*[a-zA-Z])\S+(?!\S)

Если вам не нужно использовать предварительный просмотр, то лучше всего использовать границу слова:

\b(?=\w*[0-9])(?=\w*[a-zA-Z])\w+\b 

Вы можете использовать (?i)(?<=^|\s)(\b[a-z]+\b)(?=$|\s)|. и заменить его на $1:

Imports System.Text.RegularExpressions

Module R
    Sub Main()
        Dim Rx As New Regex("(?i)(?<=^|\s)(\b[a-z]+\b)(?=$|\s)|.")
        Dim Txt As String = "WhyIsThisWordMatched XXX-111"
        Txt = Rx.Replace(Txt, "$1")
        Console.WriteLine("Result: " & Txt)
    End Sub
End Module

Ваш пример показателен, но это Visual Basic, а не VBA. Причина, по которой я использую CreateObject в VBA, заключается в том, чтобы убедиться, что он работает независимо от того, есть ли у пользователя ссылка на библиотеку, реализующую регулярные выражения, или нет. Спасибо за ваш пример.

GoWiser 22.06.2024 05:57

Другие вопросы по теме