Regex для n символов или не менее m символов

Это должен быть довольно простой вопрос с регулярным выражением, но я не мог найти ответы нигде. Как сделать регулярное выражение, которое соответствует только ТОЛЬКО 2 символам или не менее 4 символов. Вот мой текущий метод его выполнения (игнорируйте само регулярное выражение, что помимо точки):

[A-Za-z0_9_]{2}|[A-Za-z0_9_]{4,}

Однако этот метод занимает в два раза больше времени (и примерно на 0,3 секунды для меня в файле с 400 строк), поэтому мне было интересно, есть ли лучший способ сделать это?

Ответы

Ответ 1

Оптимизируйте начало и привяжите его.

^[A-Za-z0-9_]{2}(?:|[A-Za-z0-9_]{2,})$

(Кроме того, вы сказали, что игнорируете само регулярное выражение, но я догадался, что вы, вероятно, хотели 0-9, а не 0_9)

EDIT Хм, я был уверен, что прочитал, что вы хотите совместить строки. Удалите анкеры (^$), если вы хотите также совместить внутри линии. Если вы выполняете только полные строки, привязки ускоряют вас (ну, как минимум, передний якорь ^).

Ответ 2

Ваше решение выглядит неплохо. В качестве альтернативы вы можете попробовать что-то подобное:

[A-Za-z0-9_]{2}(?:[A-Za-z0-9_]{2,})?

Кстати, я думаю, что вы хотите дефис вместо подчеркивания между 0 и 9, не так ли?

Ответ 3

Правильное решение.

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

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

Ответ 4

поэтому в основном вы хотите совместить слова длины либо 2 или 2 + 2 + N, N >= 0

([A-Za-z0-9][A-Za-z0-9](?:[A-Za-z0-9][A0Za-z0-9])*)

рабочий пример:

#!/usr/bin/perl

while (<STDIN>)
{
    chomp;
    my @matches = ($_=~/([A-Za-z0-9][A-Za-z0-9](?:[A-Za-z0-9][A0Za-z0-9])*)/g);
    for my $m (@matches) {
        print "match: $m\n";
    }
}

входной файл:

cat in.txt
ab abc bcad a as asdfa
aboioioi i i abc bcad a as asdfa

выход:

perl t.pl <in.txt
match: ab
match: ab
match: bcad
match: as
match: asdf
match: aboioioi
match: ab
match: bcad
match: as
match: asdf