dd/mm/yyyy的正确正则表达式日期格式

4

我需要在一组文件中更新相同的行,该行还包括dd/mm/yyyy格式的日期和一些字符串。我查看了类似问题的答案,但无法让任何建议的模式在我的代码中运行。

我的当前PHP代码如下:

<?php
// get the system date
$sysdate = date("d/m/Y");
// open the directory
$dir = opendir($argv[1]);
$files = array();
// sorts the files alphabetically
while (($file = readdir($dir)) !== false) {
    $files[] = $file;
}
closedir($dir);
sort($files);
// for each ordered file will run the in the clauses part
foreach ($files as $file) {
    $lines = '';
    //  filename extension is '.hql'
    if (strpos($file,".hql") != false || strpos($file,".HQL") != false)
    {
        $procfile = $argv[1] . '\\' . $file;      
        echo "Converting filename: " . $procfile . "\n";
        $handle = fopen($procfile, "r");
        $lines = fread($handle, filesize($procfile));
        fclose($handle);
        $string = $lines;
        // What are we going to change runs in here
        $pattern = '[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]';
        $replacement = $sysdate;
        $lines = preg_replace($pattern, $replacement, $string);
        echo $lines;
        $newhandle = fopen($procfile, 'w+');
        fwrite($newhandle, $lines);
        fclose($newhandle);
        // DONE
    }
}

closedir($dir);

?>

当我在命令提示符上运行这段代码时,它没有给出任何错误消息,并且似乎正在正常运行。但是一旦完成并检查我的文件,我发现每个文件的内容都被删除了,它们都变成了0 KB的空文件。
6个回答

3
您的正则表达式中没有设置分隔符。
分隔符可以是任何(非字母数字、非反斜杠、非空格)字符。
您希望使用除了 / 以外的分隔符,这样就不必在模式中转义 /。
您可以使用以下内容更改格式:
$pattern = '~[0-9]{4}/[0-9]{2}/[0-9]{2}~';

请查看 在线演示


1
这个还会进行基本的检查(月份在1-12之间,日期在1-31之间)。
(0(?!0)|[1-2]|3(?=[0-1]))\d\/(0(?!0)|1(?=[0-2]))\d\/\d{4}

实时查看:http://regex101.com/r/jG9nD5


0
除了缺少分隔符(如果在模式中使用/,则#和~是首选),您还要在开头寻找4位数字:yyyy/mm/dd。决定您要寻找什么。您也可以尝试类似以下的操作:
[0-9]{4}/[0-9]{2}/[0-9]{2}

甚至

\d{4}/\d{2}/\d{2}

我知道这些可以在Perl中工作,但我还没有尝试过它们与PHP一起使用(它们应该可以工作,因为preg中的“p”代表 Perl ,但没有保证)。


非常感谢您通知我,我一直在错误的顺序中使用该模式! - user3087150

0

为什么要使用正则表达式?可以使用DateTime类进行验证。

var_dump(validateDate('2012-02-28', 'Y-m-d')); # true
var_dump(validateDate('28/02/2012', 'd/m/Y')); # true
var_dump(validateDate('30/02/2012', 'd/m/Y')); # false

函数名


0

你的代码可以像这样简短地重写:

#!/usr/bin/php
<?php
// get the system date
$sysdate = date('d/m/Y');
// change working directory to the specified one
chdir($argv[1]);
// loop over the *.hql files in sorted order
foreach (glob('*.{hql,HQL}', GLOB_BRACE) as $file) {
    echo "Converting filename: $argv[1]\\$file\n";
    $contents = file_get_contents($file);
    $contents = preg_replace('#\d{4}/\d{2}/\d{2}#', $sysdate, $contents);
    echo $contents;
    file_put_contents($file, $contents);
}

问题出在缺少PCRE正则表达式定界符,正如其他人已经指出的那样。即使修复了这个问题,代码也不是很好。
自PHP 4.3.0起,globfile_get_contents函数可用。自PHP 5起,file_put_contents函数可用。 glob使您的代码更简洁、易读,甚至具有可移植性,因为您不必在任何地方提及目录分隔符,除了信息消息。您使用了\\,但如果您想让您的代码具有可移植性,应该使用DIRECTORY_SEPARATOR

file_get_contents 函数将整个文件的内容作为字符串获取。file_put_contents 函数则相反 - 将字符串存储在文件中。如果您想在 PHP 4 中使用它,请使用此实现:

if (!function_exists('file_put_contents')):
function file_put_contents($filename, $data) {
    $handle = fopen($filename, 'w');
    $result = fwrite($handle, $data);
    fclose($handle);
    return $result;
}
endif;

同时请注意,在PHP中最后的?>并不是必需的。


谢谢,我会和我的同事分享这个内容,让他们讨论替代方案。 - user3087150
@user3087150 希望你能学会如何让你的代码更加简洁。这样做不仅更易于阅读,而且更容易调试。 - Palec

0

你应该使用定界符将正则表达式括起来。

例如:

$pattern = '![0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]!';

/ 是常用的符号,但由于正则表达式本身包含 /,所以我使用了 ! 代替。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接