从格式为“/dmY/H:i/”的字符串中提取日期和时间值或“/dmY/”

发布于 2024-08-22 16:11:08 字数 882 浏览 13 评论 0原文

解释我的问题的最好方法就是向您展示。

输入字符串:

/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 仍然需要存在,但返回空。

The best way to explain my problem is to just show you.

Input String:

/04-11-2010/12:45/

Regular Expression to get date and time parts:

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

PHP Matches Array:

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

Now the above regex works perfectly at getting the individual component parts that represent the date and time in the input string.

The problem is that the time part needs to be optional without bringing down the entire regular expression.

Problem Input String:

/04-11-2010//

PHP Matches Array

Array
(
)

Basically what I need to be returned by the matches array is:

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

Note array elements 4 and 5 still need to exist but return empty.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

往事随风而去 2024-08-29 16:11:08

使用问号运算符和非捕获组使内容成为可选。

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

我不确定它如何与匹配数组交互 - 如果空数组元素绝对重要,您可能需要选择

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

Which 有其自己的误报(当时的冒号现在是可选的)。

Use the question mark operator and a non-capturing group to make stuff optional.

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

I'm not sure how this interacts with the match array - if having the empty array elements is absolutely critical, you might need to instead go for

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

Which has its own false-positives (the colon in the time is now optional).

躲猫猫 2024-08-29 16:11:08

将第二部分设为可选:

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

此处使用无法引用的非捕获组 (?:…),因此不会更改匹配组。

Make the second part optional:

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

Here a non-capturing group (?:…) is used that cannot be referenced and thus doesn’t change the matching groups.

抹茶夏天i‖ 2024-08-29 16:11:08
  @/(\d\d)-(\d\d)-(\d\d\d\d)/((?:\d\d)?):?((?:\d\d)?)/@

做你想做的事(即填充第 4 组和第 5 组),但也接受不完整的时间,例如

    /04-11-2010/12:/

不知道这对你来说是否合适

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

does what you want (i.e. populates groups 4 and 5), but also accepts incomplete times like in

    /04-11-2010/12:/

don't know if this is fine with you

橘虞初梦 2024-08-29 16:11:08

我不是 php-head,但是怎么样:

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

就正则表达式而言,它应该匹配没有时间字段的字符串。

I'm not a php-head, but how about:

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

As far as regexps go, that should match a string that has no time field.

伴梦长久 2024-08-29 16:11:08

@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";
}

@OP, don't need messy regex.

$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";
}
妄断弥空 2024-08-29 16:11:08

使用本机 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 函数,您可以也用。

Use native PHP functions for this task, using regular expressions is a bit of an overkill.

PHP 5 has the date_parse function:

$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);

Output:

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 has a more flexible date_parse_from_format function that you could also use.

泛滥成性 2024-08-29 16:11:08

我将演示一些从时间可选的 DateTime 表达式中解析或提取数据的工作技术。请参阅此演示以获取其输出的证明。

  1. 解析日期/日期时间表达式的首要考虑因素应该是合法的日期时间解析器。仅当您有令人信服的理由时才偏离此选择。

    在这种情况下,在确定动态表达式是否具有时间分量后解析该动态表达式。无论哪种方式,请在格式参数的末尾添加一个管道,以将任何缺失的日期时间值清零。这将创建一个对象而不是数组,但根据您的下一步,这可能是从中提取值的理想来源

    <前><代码>var_export(
    日期时间::createFromFormat(
    str_contains($test, ':')
    ? '/dmY/H:i/|'
    : '/dmY//|',
    $测试

    );

  2. 提取值的理想来源

    对于填充所需数组的最直接方法,sscanf()是可行的,因为可选组件位于字符串的末尾。如果未遇到尾随时间值,它们将作为 null 元素返回。

    <前><代码>var_export(
    sscanf(
    $测试,
    '/%02s-%02s-%04s/%02[^/:]:%02[^/:]'

    );

  3. 输入到 preg_split() 的一个或多个非数字字符的正则表达式在人眼看来非常容易,并返回一个平面数组,但需要用 null< 填充/code> 当输入字符串中未提供元素时的时间元素。


    <前><代码>var_export(
    数组垫(
    预分割(
    '/\D+/',
    $测试,
    0,
    PREG_SPLIT_NO_EMPTY

    5、
    无效的
    ),
    );

  4. preg_match() 对于具有基本正则表达式技能的开发人员来说可能是一个舒适的调用,如果需要验证,它比 preg_split() 有优势,但它的输出是包含必须移走的完整字符串匹配的引用变量。将时间表达式设为可选,并设置 PREG_UNMATCHED_AS_NULL 标志,以便在缺少时间值时获得 null 元素。

    <前><代码>var_export(
    预匹配(
    '#/(\d{2})-(\d{2})-(\d{4})/(?:(\d{2}):(\d{2})/)?#' ,
    $测试,
    $匹配,
    PREG_UNMATCHED_AS_NULL

    ? array_slice($匹配项, 1)
    :[]
    );

  5. 最后,最没有吸引力的选项是对字符串进行标记。不仅在此 IIFE 内部使用循环来进行迭代 strtok() 调用,返回的数组仍然需要附加 null 时间元素。这简直就是丑陋。

    <前><代码>var_export(
    (函数($代币){
    while ($t = strtok('/:-')) {
    $tokens[] = $t;
    }
    返回 $tokens + [3 =>空,4 =>无效的];
    })([strtok($test, '/:-')])
    );

I'll demonstrate a few working techniques to parse or extract data from your time-optional DateTime expressions. See this demo for proof of their output.

  1. The first consideration for parsing date/datetime expressions should be a legitimate datetime parser. Only deviate from this choice if you have a compelling reason.

    In this case, parse the dynamic expression after determining if it has a time component. Either way, add a pipe to the end of the format parameter to zero-out any missing datetime values. This creates an object instead of an array, but depending on your next step, this may be an ideal source to extract values from

    var_export(
        DateTime::createFromFormat(
            str_contains($test, ':')
                ? '/d-m-Y/H:i/|'
                : '/d-m-Y//|',
            $test
        )
    );
    
  2. For the most direct approach to populate the desired array, sscanf() is viable because the optional components are at the end of the string. The trailing time values will be returned as null elements if they are not encountered.

    var_export(
        sscanf(
            $test,
            '/%02s-%02s-%04s/%02[^/:]:%02[^/:]'
        )
    );
    
  3. A regular expression of one or more non-digital characters fed to preg_split() is very easy on human eyes and returns a flat array, but will need to be padded with null time elements when they are not supplied in the input string.

    var_export(
        array_pad(
            preg_split(
                '/\D+/',
                $test,
                0,
                PREG_SPLIT_NO_EMPTY
            )
            5,
            null
        ),
    );
    
  4. preg_match() may be a comfortable call for developers with basic regex skills and it has the advantage over preg_split() if validation is required, but its output is a reference variable which includes the full string match which must be shifted off. Make the time expression optional and set the PREG_UNMATCHED_AS_NULL flag to gain null elements when missing time values.

    var_export(
        preg_match(
            '#/(\d{2})-(\d{2})-(\d{4})/(?:(\d{2}):(\d{2})/)?#',
            $test,
            $matches,
            PREG_UNMATCHED_AS_NULL
        )
        ? array_slice($matches, 1)
        : []
    );
    
  5. And finally, the least attractive option is to tokenize the string. Not only is a loop used inside of this IIFE to make iterated strtok() calls, the returned array still needs to append null time elements. It's just plain fugly.

    var_export(
        (function($tokens) {
            while ($t = strtok('/:-')) {
                $tokens[] = $t;
            }
            return $tokens + [3 => null, 4 => null];
        })([strtok($test, '/:-')])
    );
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文