Предполагая PCRE, используйте отрицательный взгляд вперед и взгляд назад:
(?<![\/\d])(\d+)\/(\d+)(?![\/\d])
Взгляд (группа (?=)
) говорит: «Сопоставьте это с вещами, если за ними следуют другие». Содержимое lookahead не совпадает. Мы отрицаем это (группа (?!)
) так, чтобы это
не соответствует материалу после нашей дроби - таким образом, мы не сопоставляем группу в следующем.
Дополнением к lookahead является lookbehind (группа (?<=)
) делает противоположное - оно сопоставляет вещи, если им предшествует этот другой материал, и точно так же, как lookahead, мы можем отрицать это (группа (?<!)
) чтобы мы могли сопоставлять вещи, которые не следуют чему-то.
Вместе они гарантируют, что наша фракция не будет иметь других частей фракций до или после нее. Он не предъявляет никаких других произвольных требований к входным данным. Он будет соответствовать дроби 2/3
в строке "te2/3xt"
, в отличие от большинства других предоставленных примеров.
Если ваш тип регулярного выражения использует //
s для разграничения регулярных выражений, вам придется избегать косых черт в этом или использовать другой разделитель (Perl m{}
будет хорошим выбором здесь).
Редактировать: По-видимому, ни один из этих регулярных выражений не работает, потому что механизм регулярных выражений откатывает назад и сопоставляет меньшее число для удовлетворения требований регулярного выражения. Когда я так долго работал над одним регулярным выражением, я бездействую и решаю, что, возможно, одно гигантское регулярное выражение не является ответом, и я пишу функцию, которая использует регулярное выражение и несколько других инструментов, чтобы сделать это для меня. Вы сказали, что используете Ruby. Это работает для меня:
>> def get_fraction(s)
>> if s =~ /(\d+)\/(\d+)(\/\d+)?/
>> if $3 == nil
>> return $1, $2
>> end
>> end
>> return nil
>> end
=> nil
>> get_fraction("1/2")
=> ["1", "2"]
>> get_fraction("1/2/3")
=> nil
Эта функция возвращает две части дроби, но возвращает nil
, если это дата (или если дроби нет). Это не подходит для "1/2/3 and 4/5"
, но я не знаю, хотите ли вы (или нужно), чтобы это прошло. В любом случае, я рекомендую, чтобы в будущем, когда вы спросите в Stack Overflow: «Как мне сделать регулярное выражение, чтобы соответствовать этому?» сначала вы должны сделать шаг назад и посмотреть, сможете ли вы сделать это, используя регулярное выражение и немного больше. Регулярные выражения являются отличным инструментом и могут многое, но их не всегда нужно использовать в одиночку.
РЕДАКТИРОВАТЬ 2:
Я понял, как решить проблему, не прибегая к коду без регулярных выражений, и обновил регулярное выражение. Теперь он должен работать, как и ожидалось, хотя я его не проверял. Я также пошел вперед и избежал /
с, так как вам все равно придется это делать.
РЕДАКТИРОВАТЬ 3:
Я только что исправил ошибку, указанную j_random_hacker в моих взглядах вперед и назад. Я продолжаю видеть количество усилий, прилагаемых к этому регулярному выражению, как доказательство того, что чистое решение регулярного выражения не обязательно является оптимальным решением этой проблемы.