Regex java. Зачем использовать перекресток?

Я взял из этот учебник оракула по java regex, следующий бит:

Пересечения

Чтобы создать один класс символов, соответствующий только общим символам ко всем своим вложенным классам, используйте & &, как в [0-9 && [345]]. Эта конкретное пересечение создает только один класс символов числа, общие для обоих классов символов: 3, 4 и 5.

Введите ваше регулярное выражение: [0-9 && [345]] Введите строку ввода для поиска: 3 я нашел текст "3", начинающийся с индекса 0 и заканчивающийся индексом 1.

Почему это было бы полезно? Я имею в виду, если вы хотите создать только 345, почему вместо "пересечения" не только [ 345]?

Спасибо заранее.

Ответ 1

Рассмотрим простую задачу: сопоставьте английские согласные в строке. Листинг всех согласных (или список диапазонов) будет одним из способов:

[B-DF-HJ-NP-TV-Zb-df-hj-np-tv-z]

Другой способ - использовать look-around:

(?=[A-Za-z])[^AEIOUaeiou]
(?![AEIOUaeiou])[A-Za-z]

Не уверен, есть ли другой способ сделать это без использования пересечения класса символов.

Решение пересечения класса символов (Java):

[A-Za-z&&[^AEIOUaeiou]]

Для .NET нет пересечения, но есть вычитание класса символов:

[A-Za-z-[AEIOUaeiou]]

Я не знаю детали реализации, но я не удивлюсь, если пересечение/вычитание символьного класса происходит быстрее, чем использование look-around, что является самой чистой альтернативой, если операция класса символов недоступна.

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

Другой возможный случай использования, как @beerbajay прокомментировал:

Я думаю, что встроенные классы символов являются основным прецедентом, например. [\p{InGreek}&&\p{Ll}] для строчных греческих букв.