Вопрос

Я не могу до конца разобраться в том, что ^ делает в моем preg_match.

 if (preg_match('~^(\d\d\d\d)(-(\d{1,2})(-(\d{1,2}))?)?$~', trim($date), $dateParts)) {
   echo the $dateparts and do some magic with them
 } else {
   tell me the date is formatted wrong
 }

На мой взгляд, это попытка выяснить, соответствует ли $ date формату, который я прочитал как 4 десятичных знака - 1 или 2 десятичных знака - 1 или 2 десятичных знака

если оно соответствует, то оператор IF отображает дату, если нет, то выдает ошибку неправильного форматирования даты.

Однако, просто передавая ему год $date = '1977' ни с чем другим (без дня или месяца), он по-прежнему проходит как true и отображает dateparts, я бы подумал, что это выдаст ошибку?

Может кто-нибудь указать, чего мне не хватает в регулярном выражении?Я предполагаю, что это ^ или, возможно, ? $ в конце может означать, что соответствует только его части?

Это было полезно?

Решение

Нет необходимости группироваться абсолютно все.Это выглядит приятнее и будет делать то же самое:

preg_match('~^\d{4}(-\d{1,2}(-\d{1,2})?)?$~', trim($date), $dateParts)

Это также объясняет , почему "1977" принимается - части месяца и дня являются и то, и другое необязательно (вопросительный знак делает что-то необязательным).

Чтобы сделать то, что вы говорите ("4 десятичных знака - 1 или 2 десятичных знака - 1 или 2 десятичных знака"), вам нужно удалить обе необязательные группы:

preg_match('~^\d{4}-\d{1,2}-\d{1,2}$~', trim($date), $dateParts)

Тот самый "^" и "$" не имеет никакого отношения к проблеме, которую вы видите.Это просто якоря начала строки и конца строки, гарантирующие, что больше ничего чем то, что описывает шаблон, находится в отмеченной строке.Оставь их в покое и "blah 1977-01-01 blah" начнет совпадать.

Другие советы

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

'~^(\d\d\d\d)-(\d{1,2})-(\d{1,2})$~'

Проблема заключалась в том, что регулярное выражение разрешало указывать месяц и день как необязательные с помощью символа '?'.

^ и $ привяжите свой шаблон к началу и концу соответственно переданной строки.В ? является множителем, соответствующим 0 или 1 предыдущему шаблону (в данном случае биту, заключенному в скобки).

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

^    # beginning of string
    (\d\d\d\d)   #year
    (
        -(\d{1,2})   #month after a dash
        (
            -(\d{1,2}) #date after a dash
        )? #date optional
    )?   # month and date optional
$   # end of string

Ладно, давай покончим с этим ради тебя:

  • '~^(\d\d\d\d)(-(\d{1,2})(-(\d{1,2}))?)?$~'
  • ~ - в начале и в конце находятся разделители регулярных выражений, поэтому на самом деле они не являются частью регулярного выражения.
  • ^ - Означает "Это начало пути".
    • Избегает совпадений в середине строки и привязывает ее так, чтобы начало строки должно совпадать
  • (\d\d\d\d\d) - Сопоставляет (и фиксирует) четыре цифры и не является необязательным
    • Это также можно было бы записать как \d{4}
  • (-(\d{1,2})(-(\d{1,2})))?)? - Сопоставляет (и захватывает) необязательную группу.
    • В нем говорится, что если эта группа существует, то она должна состоять из тире, за которым следует одна или две цифры (день или месяц), за которыми следует тире, за которым следуют одна или две цифры (день или месяц).
  • $ - Означает конец строки, так что это вместе с ^ в начале строки означает, что вся строка должна соответствовать регулярному выражению.

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

  • 1982-08-11
  • 1982-30-01
  • 8127-99-52

Некоторые примеры, которые НЕ будут соответствовать:

  • 82-08-11
  • 2009-10

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top