Проблема с простым регулярным выражением в PHP - PullRequest
0 голосов
/ 24 февраля 2010

Лучший способ объяснить мою проблему - просто показать вам.

Строка ввода:

/04-11-2010/12:45/

Регулярное выражение для получения даты и времени:

preg_match('@/(\d\d)-(\d\d)-(\d\d\d\d)/(\d\d):(\d\d)/@', $input, $matches);

Массив соответствий PHP:

Array
(
    [0] => /01-11-2010/12:45/
    [1] => 01
    [2] => 11
    [3] => 2010
    [4] => 12
    [5] => 45
)

Теперь приведенное выше регулярное выражение отлично работает для получения отдельных компонентов, которые представляют дату и время во входной строке.

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

Строка ввода проблемы:

/04-11-2010//

Массив соответствий PHP

Array
(
)

По сути, мне нужно вернуть массив совпадений:

Array
(
    [0] => /01-11-2010/12:45/
    [1] => 01
    [2] => 11
    [3] => 2010
    [4] => 
    [5] => 
)

Обратите внимание, что элементы массива 4 и 5 все еще должны существовать, но возвращать пустой.

Ответы [ 6 ]

2 голосов
/ 24 февраля 2010

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

@/(\d\d)-(\d\d)-(\d\d\d\d)/(?:(\d\d):(\d\d))?/@

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

@/(\d\d)-(\d\d)-(\d\d\d\d)/((?:\d\d)?):?((?:\d\d)?)/@

Который имеет свои ложные срабатывания (двоеточие во времени теперь необязательно).

1 голос
/ 24 февраля 2010
  @/(\d\d)-(\d\d)-(\d\d\d\d)/((?:\d\d)?):?((?:\d\d)?)/@

делает то, что вы хотите (то есть заполняет группы 4 и 5), но также принимает неполное время, как в

    /04-11-2010/12:/

не знаю, нормально ли это с тобой

1 голос
/ 24 февраля 2010

Сделать вторую часть необязательной:

'@/(\d\d)-(\d\d)-(\d\d\d\d)/(?:(\d\d):(\d\d))?/@'

Здесь используется группа без захвата (?:…), на которую нельзя ссылаться, и, следовательно, она не изменяет соответствующие группы.

0 голосов
/ 24 февраля 2010

Используйте встроенные функции PHP для этой задачи, использование регулярных выражений немного излишне.

PHP 5 имеет функцию date_parse :

$string = '/04-11-2010/12:45/';
$dateArray = date_parse(str_replace('/', ' ', $string));
print_r($dateArray);

$string = '/04-11-2010//';
$dateArray = date_parse(str_replace('/', ' ', $string));
print_r($dateArray);

Выход:

Array
(
    [year] => 2010
    [month] => 11
    [day] => 4
    [hour] => 12
    [minute] => 45
    [second] => 0
    [fraction] => 0
    [warning_count] => 0
    [warnings] => Array
        (
        )

    [error_count] => 0
    [errors] => Array
        (
        )

    [is_localtime] => 
)

Array
(
    [year] => 2010
    [month] => 11
    [day] => 4
    [hour] => 
    [minute] => 
    [second] => 
    [fraction] => 
    [warning_count] => 0
    [warnings] => Array
        (
        )

    [error_count] => 0
    [errors] => Array
        (
        )

    [is_localtime] => 
)

PHP 5.3 имеет более гибкую date_parse_from_format функцию, которую вы также можете использовать.

0 голосов
/ 24 февраля 2010

@ OP, не нужно беспорядочное регулярное выражение.

$str="/04-11-2010/12:45/";
$s = array_filter(explode('/',$str));
$date=$s[1];
$time=$s[2];
$date_parts=explode("-",$date);
$time_parts=explode(":",$time);
if ( checkdate($date_parts[1],$date_parts[0],$date_parts[2]) ){
    print "date ok\n";
}
0 голосов
/ 24 февраля 2010

Я не php-руководитель, но как насчет:

preg_match('@/(\d\d)-(\d\d)-(\d\d\d\d)/(\d\d)?:?(\d\d)?/@', $input, $matches);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...