Регулярные выражения и повторяющиеся классы символов в Perl

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

Я мог бы сделать что-то вроде этого: /^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]/

но есть ли лучший способ?

Похоже на оператор повтора:

a{n} Соответствует 'a', повторяющемуся ровно n раз.

a{n,} Соответствует 'a', повторяющемуся n или более раз.

a{n, m} Соответствует 'a', повторяющемуся от n до m раз включительно.

Будет работать, но следующее регулярное выражение не работает:

/^[A-Fa-f0-9]{4}+/

Я пытаюсь сопоставить такие строки, как:

AA00

AA00FFAA

0011FFAA0022

и так далее. Каждая строка будет на отдельной строке.

Спасибо!


person user210099    schedule 30.06.2011    source источник
comment
Вы также можете сказать [[:xdigit:]] вместо [A-Fa-f0-9]. Это более четко передает намерение ИМХО.   -  person Sean    schedule 01.07.2011
comment
@Sean: \p{ahex} бесконечно лучше: шум [[:posix:]] - это именно то.   -  person tchrist    schedule 01.07.2011


Ответы (2)


Попробуй это:

/^(?:[A-Fa-f0-9]{4})+$/
person agent-j    schedule 30.06.2011
comment
Да, это работает идеально. Не могли бы вы объяснить, как именно это работает? Я понимаю, что () создает группу, доступную $1.. $2 и т. д., но как ?: вступает в игру? Справочная страница, к которой я обычно обращаюсь для этих вещей, объясняет это следующим образом: (?:regex): скобки без захвата группируют регулярное выражение, поэтому вы можете применять операторы регулярного выражения, но ничего не захватывает и не создает обратные ссылки. - person user210099; 01.07.2011
comment
Точно. Поскольку вы можете использовать все значение совпадения, вам не нужно нести дополнительные расходы на захват материала внутри круглых скобок. Это простая оптимизация. Так что из-за (?:) вы не получите значение в match.Groups[1]. Это единственная разница. - person agent-j; 01.07.2011
comment
Более того...... Что произойдет, если мне нужно будет поддерживать ряд фиксированных символов между шестнадцатеричными числами.. Скажем, \z является разделителем, например, \zaa00\zffff\z0101 ? Я попытался изменить ваше регулярное выражение, но я все еще работаю над его пониманием. Большое спасибо за ваши чрезвычайно полезные ответы! - person user210099; 01.07.2011
comment
Добавьте (?:\\z|$), чтобы он соответствовал либо \z, либо $ (конец строки). Я думаю, что это так, но я никогда не могу вспомнить, как избежать слэшей в perl. /^(?:[A-Fa-f0-9]{4}(?:\\\\z|$))+$/ - person agent-j; 01.07.2011
comment
когда косая черта является частью того, что я пытаюсь сопоставить, я обычно использую m:/stuf/: вместо m/\/stuf\//. - person flies; 09.08.2013
comment
Я вижу проблему с этим решением. Строка Ab82 также будет соответствовать. Думаю, стоит добавить проверку на равенство двух символов. - person Vladimir; 26.12.2015

У вас есть вложенные квантификаторы в регулярном выражении; т. е. {4} означает совпадение ровно 4 раза, а + означает совпадение этой строки много раз, поэтому эти два квантификатора конфликтуют. Если вы просто удалите +, это сработает:

/^[A-Fa-f0-9]{4}/
person Corey Henderson    schedule 30.06.2011
comment
За исключением ^, который соответствует началу строки. - person agent-j; 01.07.2011
comment
Он также хочет сопоставить AA00FFAA и 0011FFAA0022. т. е. любая последовательность длины 4N - person Jacob Eggers; 01.07.2011
comment
Я не вижу в этом проблемы? В вопросе также есть ^, и все строки примеров начинаются с совпадения. - person Corey Henderson; 01.07.2011
comment
он будет соответствовать только первым 4 символам строки. Вам нужно сопоставить числа, кратные 4, начиная с начала строки. - person agent-j; 01.07.2011
comment
/^[A-Fa-f0-9]{4}/ также будет соответствовать шести шестнадцатеричным символам, которые ему не нужны. например AA00FF - person Jacob Eggers; 01.07.2011