Регулярное выражение: еще один случай «Соответствие всем строкам, ЗА ИСКЛЮЧЕНИЕМ определенной серии строк».

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

ЧТО Я ПЫТАЮСЬ СДЕЛАТЬ:

Я работаю над импортом данных в нашу новую базу данных. Большая часть преобразования была сделана несколько месяцев назад, и теперь мне нужно преобразовать все новые данные.

ОБЩАЯ ИНФОРМАЦИЯ ОБ ОКРУЖАЮЩЕЙ СРЕДЕ:

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

- Kid
- No Mail
- Household

Однако столбец в исходном файле имеет гораздо больше значений, которые я хочу игнорировать.

Программа импорта имеет функцию создания «Словарей», которые можно применять к определенному полю для преобразования импортированного значения в стандартное значение в базе данных. Это отлично подходит для исправления распространенных опечаток и т. д.

Словарь очень простой. У вас есть список правильных значений, и у каждого правильного значения может быть несколько неправильных значений.

Например:

    CORRECT VALUE           IMPORT VALUES
    Kid                     kid
                            kids
                            Child
                            Minor

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

ПРОБЛЕМА, КОТОРУЮ НУЖНО РЕШИТЬ:

Вот пример файла словаря:

     CORRECT VALUE LIST     IMPORT VALUE
  -  Kid                    Kid
                            KID

  -  No Mail                No Mail
                            NO MAIL

  -  Household              HH

  -  OTHER                Regex expression to match: Anything else

ПРИМЕРЫ:

Входное значение:

  • KID превращается в Kid
  • HH превращается в Household
  • John превращается в OTHER
  • Do Not Call превращается в OTHER
  • NO MAIL превращается в No Mail
  • ABCD превращается в OTHER

ЧТО Я СДЕЛАЛ:

Это то, что я нашел в Интернете и адаптировал для своего случая:

Формула найдена на codinghorror.com:

(?!kid|KID|Kid\b)\b\w+ - Это работает для «KID», но не работает, когда я добавляю что-то еще по какой-то причине

Формула найдена на stackoverflow.com:

^(?!kid$).* — подходит ко всему, даже к «Малышу».

^((?!kid).)*$ - То же

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

Поэтому любая помощь или указатель, который вы можете мне дать, ценятся.

Спасибо!


person philips    schedule 16.09.2013    source источник
comment
formula found on codinghorror.com - вот это отличие. )   -  person raina77ow    schedule 16.09.2013
comment
Если говорить серьезно, я все еще не могу понять ваш вопрос, возможно, потому, что он в основном касается решений, которые вы разработали, а не проблемы. Перефразировать его, четко указав, что на входе программы и что должно быть на выходе, может быть полезно не только мне. )   -  person raina77ow    schedule 16.09.2013
comment
@raina77ow: Спасибо. Я добавил несколько примеров. Я надеюсь, что это проясняет это.   -  person philips    schedule 16.09.2013


Ответы (2)


Я настоятельно рекомендую найти другое решение для вашей работы по импорту, так как это очень быстро станет громоздким. Однако, если вы действительно хотите, вот как создать регулярное выражение, которое, по крайней мере, будет делать то, что вы просите (если я вас правильно понял, и если ваш механизм регулярных выражений поддерживает эту форму, поскольку вы не упомянули, какой из них вы используете ).

(?!^(kid|KID|Kid|no mail)$).*

Это означает, что ^ соответствует началу строки, а $ — концу строки (или иногда началу и концу строк, но если это все однострочные значения, это не имеет значения). Вы можете обернуть что угодно в (?!), что означает «не совпадать, если это соответствует», а .* вообще соответствует чему угодно. Ввод | между двумя шаблонами соответствует любому из этих шаблонов. Итак, если какая-либо из строк в середине разделена символом | совпадение, и нет ничего до или после (это то, что означают ^ и $), тогда бит внутри (?!) совпадает, и если это совпадает, то вещь в целом не совпадает. Если первый бит в порядке, то .* будет соответствовать чему угодно, поэтому объект в целом будет соответствовать.

Вот как вы это делаете, но подумайте о том, чтобы переосмыслить проблему, поскольку почти наверняка есть лучшее решение для того, что вы пытаетесь сделать. Удачи!

person Thomas Parslow    schedule 16.09.2013
comment
Спасибо за ваш ответ. Честно говоря, у меня от этого немного начинает дымиться голова. (Я уверен, что скоро освою это!). Я попробовал ваше решение, и когда я ввожу 'Kid', он возвращает 'k'. Все остальное соответствует и возвращает пустое значение. .. Я не уверен в используемом движке. Программа базы данных, которую я использую, называется Raiser's Edge от Blackbaud. Программа импорта, которую я использую, называется Import-O-Matic и представляет собой плагин для Raiser's Edge. Думаю, Import-O-Matic был написан на VB.Net. Пожалуйста, извините мое невежество, но я надеюсь, что это ответит на ваш вопрос. - person philips; 17.09.2013
comment
Каретка (^) должна выходить за пределы просмотра вперед, как это есть в ОП. Как у вас есть, регулярное выражение будет соответствовать каждой позиции, которая не является началом строки, просто потому, что это не начало строки. - person Alan Moore; 17.09.2013
comment
@ Алан Мур: Спасибо за ваши ответы. Я чувствую, что должен уточнить, что длина ввода не превышает 12 символов (и исходит из таблицы csv). ВСЕ входное значение не может быть: kid|Kid|no Mail|HH и т. д. Нам не нужно искать во входной строке. - person philips; 17.09.2013
comment
Вот что я говорю. С кареткой за пределами предпросмотра регулярное выражение пытается найти совпадение в начале, и если это не удается, оно терпит неудачу. Если оно находится внутри просмотра вперед, регулярное выражение будет пытаться сопоставить последующие позиции. Необходимо привязать все регулярное выражение, а не только опережающее выражение. - person Alan Moore; 17.09.2013
comment
Ok. Я как-то заставил это работать: ^(?!(Kid|Household|No Mail)$).* . Я не уверен, почему это работает, но это дает желаемый эффект в моей среде. Если это имеет смысл для кого-то еще, пожалуйста, дайте мне знать. Возможно, мое программное обеспечение слишком специализировано или настроено. - person philips; 17.09.2013

Короче говоря, у вас есть список возможных выходных значений и для каждого такого значения конечный набор возможных значений, «совпадающих» с ним во входных данных. Похоже, что эти matches нечувствительны к регистру, но на самом деле это может быть не так для всех из них.

Теперь задача проста: для каждой входной строки попытаться сопоставить ее с этим набором. Если он соответствует определенному шаблону, узнайте, какому выходному значению он принадлежит, и поместите его в набор результатов. Если нет, используйте пустое значение, которое вы установили (пустая строка, насколько я понимаю).

Переходя от теории к практике, вот как этот подход можно реализовать в JavaScript:

// defining the dictionary: each key is a possible output value,
// each element is a list of matching words
var dictionary = {
    Kid:       ['kid', 'kids', 'child', 'minor'],
    'No Mail': ['no mail'],
    HouseHold: ['HH']
};
var defaultOutput = ''; // self-explanatory

// preparing the dictionary of patterns
var outputs = Object.keys(dictionary), 
    patternsToMatch = {};

outputs.forEach(function(outValue) {
    var alternationPart = dictionary[outValue].join('|');
    patternsToMatch[outValue] = new RegExp(
        '^(?:' + alternationPart + ')$', 'i');
});

// actually processing the inputs:
var testInputs = ['KiD', 'kidi', 'cHiLd', 'no mail', 'no email'];
console.log(testInputs);

var results = testInputs.map(function(inputStr) {
    var matchingOutput = defaultOutput;
    outputs.some(function(outputVal) {
        if (patternsToMatch[outputVal].test(inputStr)) {
            matchingOutput = outputVal;
        }
        return matchingOutput !== defaultOutput;
    });
    return matchingOutput;
});
console.log(results);

JS-скрипт.

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

person raina77ow    schedule 16.09.2013
comment
Большое спасибо. Ваше описание выше вполне правильное, лаконичное и простое. На данный момент я заставил регулярное выражение как-то работать. Однако я буду ссылаться на ваш пример java-скрипта, если мне понадобится что-то подобное в будущем. - person philips; 17.09.2013