Разделение слов различными способами с помощью 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. Переход от буквы к номеру или цифры к букве
  3. (Необязательно) разделить на несколько других символов (- _)

Моя главная проблема - 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]+ 
Другие вопросы по тегам