从头开始匹配字符串的一部分

时间:2016-05-17 14:53:50

标签: php regex date

我有一个约会(例如yyyy-mm-dd hh:mm:ss)我希望能够返回true如果我们有一个字符串匹配该模式,完全或部分匹配该模式,从头开始结束例如。 44会匹配该模式,因为-12会匹配yy,但-不匹配,因为preg_match不是有效的“y”字符。

我发现了一些不优雅的解决方案。我可以对#^\d(\d(\d(\d(-)?)?)?)?$# 做类似的事情:

$patterns = [
    '',
    '\d',
    '\d\d',
    '\d\d\d',
    '\d\d\d\d',
    '\d\d\d\d-',
    ...
];
isset($patterns[strlen($str)] && preg_match('#^' . $patterns[strlen($str)] . '$#', $str)

根据年份执行部分匹配。它需要扩展到占月,日,小时,分钟等,但这应该显示想法#1。

我也可以做点像......

switch (strlen($str)) {
    case 1: return preg_match('#^\d$#', $str);
    case 2: return preg_match('#^\d\d$#', $str);
    case 3: return preg_match('#^\d\d\d$#', $str);
    case 4: return preg_match('#^\d\d\d\d$#', $str);
    case 5: return preg_match('#^\d\d\d\d-$#', $str);
    ...
}

但这种情况似乎也很复杂。

我也可以这样做:

2005-

但这似乎也很臃肿。

换句话说,我正在寻找2将返回true的函数,2005-1-2005也是如此。但205-将返回false,neubertWHERE date_column LIKE '$str%'也会返回。

我希望能够将有效值传递给SQL查询。例如。 date_column。如果-12-是DATETIME,则搜索date_column会浪费时间,因为<head>无法将其作为值。

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

根据您的问题下方的评论,如果我理解正确的问题,您可以使用此单一正则表达式来匹配您的输入:

^(?:\d{1,3}|\d{4}(?:-(?:\d{1,2}(?:-\d{0,2})?)?)?)$

RegEx Demo

答案 1 :(得分:2)

这样的事情应该有效:

function doesMatch($str) {
    // The date pattern split so that each array entry matches exactly one character
    $pattern_chunks = array(
        '\d', '\d', '\d', '\d', '-',
        '\d', '\d', '-',
        '\d', '\d',
        '\s',
        '\d', '\d', ':',
        '\d', '\d', ':',
        '\d', '\d'
    );

    $chunk_count = count($pattern_chunks);
    $str_len = strlen($str);

    // If the string is empty, it's clearly not a date
    if ( $str_len < 1 ) { return false; }

    // If the string is longer than our pattern chunks, there's no way it matches
    if ( $str_len > $chunk_count ) { return false; }

    // Make a pattern using the first N chunks of our pattern parts
    $pattern = '^' . implode('', array_slice($pattern_chunks, 0, $str_len)) . '$';

    // Return if the string matches
    return (preg_match($pattern, $str) > 0);
}

例如,您的输入字符串长度为6个字符,它仅使用日期模式的前6个块(^\d\d\d\d-\d$)。

答案 2 :(得分:1)

我知道这个问题已经得到解决和关闭,但我认为这是一个有趣的挑战,我决心提出一个非正则表达式解决方案。我还希望它更具可重用性,而不是针对一个特定情况进行硬编码。

这是我最终的结果;我相信它可以进一步改进! :)

// case-insensitive string format comparison
// if $strict is true, the string lengths must also match
// if $strict is false, the strings are compared left to right
function strfcasecmp($str, $format, $strict = false) {
    $len1 = strlen($str);
    $len2 = strlen($format);

    // make sure we have a valid length
    if ($len1 < 1 || $len1 > $len2) {
        return false;
    }

    // if strict, make sure length matches as well
    if ($strict) {
        if ($len1 !== $len2) {
            return false;
        }
    }

    // compare alpha, numeric, space & printable characters
    for ($i = 0; $i < $len1; $i++) {
        switch (true) {
            case ctype_alpha($format[$i]):
                if (!ctype_alpha($str[$i])) {
                    return false;
                }
                break;

            case ctype_digit($format[$i]):
                if (!ctype_digit($str[$i])) {
                    return false;
                }
                break;

            case ctype_space($format[$i]):
                if (!ctype_space($str[$i])) {
                    return false;
                }
                break;

            case ctype_punct($format[$i]):
                if ($str[$i] !== $format[$i]) {
                    return false;
                }
                break;

            default:
                // character must match at least one type specified above
                return false;
        }
    }

    return true;
}

基于原始问题的使用示例:

$format = '0000-00-00 00:00:00';
var_dump(strfcasecmp('44', $format)); // true
var_dump(strfcasecmp('-12', $format)); // false
var_dump(strfcasecmp('2005-', $format)); // true
var_dump(strfcasecmp('2', $format)); // true
var_dump(strfcasecmp('2005-1', $format)); // true
var_dump(strfcasecmp('-2005', $format)); // false
var_dump(strfcasecmp('205-', $format)); // false
var_dump(strfcasecmp('neubert', $format)); // false

答案 3 :(得分:0)

您也可以使用strpos()匹配:

$a = "2016-05-17 was a good day.";
if (strpos(substr($a, 0, 10), '2016-05-17') !== false) {
    echo "Indeed it was";
}