До сих пор в качестве примеров умышленно рассматривались простые регулярные выражения, чтобы использование в них метасимволов и литералов было предельно очевидным. Однако в большинстве практически интересных случаев для построения регулярных выражений необходим структурный анализ лексем входного потока. Структурный подход иллюстрируют несколько примеров конструирования регулярных выражений для распознавания времени и даты, которые рассмотрены ниже.
В первом примере рассматривается проблема конструирования регулярного выражения для поиска записей даты, которые состоят из сокращенного названия месяца года и числа месяца. Допустим, требуется составить регулярное выражение для распознавания январских дат, например, в следующем формате: Jan 31, Jan 7 или Jan 07. На первый взгляд кажется, что проблему легко решает следующее регулярное выражение:

Jan[ ][0123][0-9]

Однако это регулярное выражение теряет корректные даты, где число задано одной цифрой без лидирующего нуля, например, Jan 7. Кроме того, оно будет находить несуществующие даты, например, Jan 00 или Jan 32. Один из способов корректного поиска даты заключается в том, чтобы разделить диапазон чисел января на три группы, которые соответствуют декадам. Каждая декада января должна специфицироваться своим фрагментом регулярного выражения. Спецификации декад объединяются в следующую итоговую конструкцию выбора:

Jan[ ](0?[1-9]|[12][0-9]|3[01])

В этом регулярном выражении первая альтернатива 0?[1-9] обеспечивает поиск дат первой декады от 1-го до 9-го января, допуская запись чисел с лидирующим нулем. Вторая альтернатива [12][0 9] позволяет распознавать даты в диапазоне чисел с 10-го по 29-е января. Наконец, последняя альтернатива находит завершающие даты 30-е и 31-е января. Таким образом, этим регулярным выражением оказываются покрыты все декады и числа января.
Существует другое решение задачи поиска даты, в котором используется иной принцип декомпозиции диапазона чисел января. Его представляет следующее регулярное выражение:

Jan[ ](31|[123]0|[012]?[1-9])

Это регулярное выражение также объединяет три альтернативы. Первая альтернатива допускает только одно число, 31-е января. Вторая альтернатива специфицирует регулярное выражение для поиска дат, в которых числа кратны 10-ти, то есть 10-е, 20-е и 30-е января. Последняя альтернатива соответствует всем остальным датам января.
На первый взгляд кажется, что рассмотренные регулярные выражения легко приспособить для лексического анализа даты в любом месяце года, если заменить обозначение января следующей конструкцией выбора:

(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)

Однако в этом случае возникает опасность распознавания несуществующих дат, например, Jun 31 (31-е июня), из-за того, что количество дней в разных месяцах года различно. Поэтому целесообразно построить различные альтернативы для групп месяцев равной продолжительности и объединить их с помощью конструкции выбора.
В частности, для распознавания дат месяцев январь, март, май, июль, август, октябрь и декабрь, с продолжительностью 31 день, может быть использована следующая альтернатива:

(Jan|Mar|May|Jul|Aug|Oct|Dec)[ ](0?[1-9]|[12][0-9]|3[01])

Соответствующая альтернатива для месяцев апрель, июнь, сентябрь и ноябрь, где только 30 дней, имеет следующий вид:

(Apr|Jun|Sep|Nov)[ ]([123]0|[012]?[1-9])

Наконец, для февраля, где может быть либо 28, либо 29 дней, требуется составить следующую отдельную альтернативу:

Feb[ ](0?[1-9]|[12][0-9])

Для более лаконичной записи этих трех альтернатив можно ввести регулярные определения DATE31, DATE30 и FEBRUARY, соответственно. Тогда их объединение с помощью конструкции выбора образует следующее регулярное выражение, которое обеспечивает поиск дат любого месяца года, независимо от продолжительности месяца:

{DATE31}|{DATE30}|{FEBRUARY}

В некоторых случаях необходимо обеспечить поиск дат, где кроме числа и месяца указан год. В общем случае год может представляться любыми натуральными числами. Регулярное выражение для спецификации натуральных чисел было рассмотрено выше, для иллюстрации применения квантификатора итерации. Таким образом, составление регулярного выражения для корректного распознавания даты в общем случае превращается в сложную проблему, особенно когда необходимо различать високосные и не високосные годы при анализе февральских дат.
Еще один пример, где для конструирования регулярного выражения применяется структурный подход, демонстрирует, каким образом может быть решена задача поиска во входном потоке записей времени суток. Допустим, во входном потоке требуется находить записи времени в 12 ти часовом формате AM/PM, где часы, минуты и необязательные секунды, разделены символом двоеточия, например, 10:15:00, 8:30 или 08:30:00. Очевидно, что регулярное выражение, которому соответствует указанный формат времени суток, должно состоять из трех частей, которые специфицируют часы, минуты и необязательные секунды, соответственно.
Наиболее просто составить регулярное выражение для распознавания записи минут и секунд. Запись минут или секунд должна состоять из двух десятичных цифр, причем первая цифра ограничена диапазоном от 0 до 5, а вторая цифра может быть любой. Таким образом, для распознавания записи минут или секунд можно рекомендовать следующий регулярный фрагмент, который образует конкатенация двух символьных классов:

[0-5][0-9]

Чтобы специфицировать регулярное выражение для распознавания часов, нужно рассмотреть два отдельных случая, когда запись часов состоит из двух и из одной значащей цифры. При этом необходимо учесть, что первая цифра записи часа из двух цифр может быть только 1, а вторая цифра может представляться 0, 1 или 2. Когда запись часа состоит только из одной цифры, она может быть любой.
Объединение этих двух альтернатив в конструкции выбора образует следующий фрагмент регулярного выражения для распознавания записи часов:

1[012]|[1-9]

Конкатенация рассмотренных регулярных фрагментов для записей часов, минут и необязательных секунд позволяет составить следующее регулярное выражение для поиска времени суток в 12-ти часовом формате AM/PM:

(1[012]|[1-9]):[0-5][0-9](:[0-5][0-9])?[ ](am|pm)

В этом регулярном выражении круглые скобки используются для ограничения области действия конструкций выбора и группировки необязательных символьных классов, которые обозначают секунды.
Допустим теперь, что во входном потоке требуется находить записи времени в 24-часовом формате, где часы, минуты и необязательные секунды по-прежнему должны быть разделены символом двоеточия, например, 23:59:59, 8:30 или 08:30. Очевидно, что регулярное выражение, которому соответствует указанный формат времени суток, также должно состоять из трех частей, которые специфицируют часы, минуты и необязательные секунды, соответственно. Совершенно понятно, что фрагменты регулярных выражений для записи минут и секунд должны быть идентичны в обеих шкалах измерения времени суток. Однако регулярное выражение для записи часов должно строится на основе иных соображений. Чтобы специфицировать регулярное выражение для записи часов, естественно разделить сутки на три группы часов: утро, от 0 до 9-ти часов, день, от 10-ти до 19-ти часов и вечер, от 20-ти до 23-х часов. Очевидно, что объединение этих трех альтернатив в регулярном выражении покрывает суточный диапазон в часах. Наиболее простое решение, которое отражает предложенную декомпозицию часов и спецификацию минут, реализует следующее регулярное выражение:

(0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?

Аналогично рассмотренному выше регулярному выражению для поиска времени суток в 12-ти часовом формате AM/PM, в этом регулярном выражении символьные классы после двоеточия специфицируют запись минут и необязательных секунд, а объединение альтернатив, ограниченное круглыми скобками, обеспечивает распознавание любого часа суток. Композиция первых двух альтернатив в круглых скобках на основании дистрибутивного закона позволяет получить следующее логически менее очевидное, но более компактное регулярное выражение, которое эквивалентно регулярному выражению, рассмотренному выше:

([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?

Формальную эквивалентность обоих регулярных выражений для времени суток доказывает следующая цепочка тождественных преобразований первых двух альтернатив исходного регулярного выражения:

0?[0-9]|1[0-9] = 0[0-9]|[0-9]|1[0-9] = (0|1)?[0-9] = [01]?[0-9]

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

{DATE}[ ]{TIME}[ ]{YEAR}

В этом регулярном выражении для сокращения записи используются регулярные определения DATE, TIME и YEAR, которые обозначают рассмотренные выше регулярные фрагменты, специфицирующие дату, время и год, соответственно. Оно позволяет обнаружить во входном потоке, например, следующую запись: Jan 1 00:00:00 1970, которая обозначает базовую точку отсчета, принятую в OS UNIX для измерения временных интервалов.
Обобщая полученные результаты, следует отметить, что рассмотренные примеры иллюстрируют применение принципа декомпозиции, который наиболее часто используется для составления регулярных выражений в сложных случаях, когда решение неочевидно и необходим структурный анализ проблемы. Принцип декомпозиции состоит в том, чтобы заменить решение сложной исходной проблемы рассмотрением различных частных альтернатив, которые затем объединяются в результирующее регулярное выражение с помощью конструкции выбора или конкатенации обязательных фрагментов.