Разделение слов различными способами с помощью Regex
Работает над чем-то похожим на Solr WordDelimiterFilter, но не на Java.
Хотите разбить слова на токены, как это:
P90X = P, 90, X (split on word/number boundary)
TotallyCromulentWord = Totally, Cromulent, Word (split on lowercase/uppercase boundary)
TransAM = Trans, AM
Ищем общее решение, не специфичное для приведенных выше примеров. Желательно в стиле regex, который не поддерживает lookbehind, но я могу использовать PL/perl, если необходимо, что может делать lookhhind.
Нашел несколько ответов на SO, но все они, похоже, использовали lookhehind.
Вещи, чтобы разделить на:
- Переход от строчной буквы к прописной
- Переход от буквы к номеру или цифры к букве
- (Необязательно) разделить на несколько других символов (- _)
Моя главная проблема - 1 и 2.
2 ответа
Это не то, что я хотел бы обойтись без оглядки назад, но для решения проблемы, вот решение javascript, которое вы сможете легко преобразовать в любой язык:
function split(s) {
var match;
var result = [];
while (Boolean(match = s.match(/([A-Z]+|[A-Z]?[a-z]+|[0-9]+|([^a-zA-Z0-9])+)$/))) {
if (!match[2]) {
//don't return non alphanumeric tokens
result.unshift(match[1]);
}
s = s.substring(0, s.length - match[1].length);
}
return result;
}
Демо:
P90X [ 'P', '90', 'X' ]
TotallyCromulentWord [ 'Totally', 'Cromulent', 'Word' ]
TransAM [ 'Trans', 'AM' ]
URLConverter [ 'URL', 'Converter' ]
Abc.DEF$012 [ 'Abc', 'DEF', '012' ]
Это регулярное выражение должно разбивать на токены все слова в абзаце или строке.
Даже работает для простого случая в вашем примере.
Матч глобально. Кроме того, если вы хотите добавить другие конкретные разделители, которые также могут быть сделаны.
# /(?:[A-Z]?[a-z]+(?=[A-Z\d]|[^a-zA-Z\d]|$)|[A-Z]+(?=[a-z\d]|[^a-zA-Z\d]|$)|\d+(?=[a-zA-Z]|[^a-zA-Z\d]|$))[^a-zA-Z\d]*|[^a-zA-Z\d]+/
(?:
[A-Z]? [a-z]+
(?= [A-Z\d] | [^a-zA-Z\d] | $ )
|
[A-Z]+
(?= [a-z\d] | [^a-zA-Z\d] | $ )
|
\d+
(?= [a-zA-Z] | [^a-zA-Z\d] | $ )
)
[^a-zA-Z\d]*
|
[^a-zA-Z\d]+