4

I need to update the same line, which is also including a date in dd/mm/yyyy format along with some string, in a group of files. I have checked answers here given to similar questions however couldn’t make any of the patterns suggested run in my code.

My current PHP code is:

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

?>

When I run this code on command prompt, it doesn’t give any error message and it seems to be running properly. But once it finishes and I check my files, I see that the content of each file is getting deleted and they all become 0 KB files with nothing in them.

Palec
  • 12,743
  • 8
  • 69
  • 138
user3087150
  • 53
  • 1
  • 5

6 Answers6

3

You have no delimiters set in place for your regular expression.

A delimiter can be any (non-alphanumeric, non-backslash, non-whitespace) character.

You want to use a delimiter besides / so you avoid having to escape / already in your pattern.

You could use the following to change your format:

$pattern = '~[0-9]{4}/[0-9]{2}/[0-9]{2}~';

See Live demo

hwnd
  • 69,796
  • 4
  • 95
  • 132
1

This one also do basic checks (month between 1-12, day between 1-31)

(0(?!0)|[1-2]|3(?=[0-1]))\d\/(0(?!0)|1(?=[0-2]))\d\/\d{4}

See it live: http://regex101.com/r/jG9nD5

Teejay
  • 7,210
  • 10
  • 45
  • 76
0

You should surround the regular expression with delimiter character.

For example:

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

/ is commonly used, but because the regular expression contains / itself, I used ! instead.

falsetru
  • 357,413
  • 63
  • 732
  • 636
0

Besides the lack of delimiters (# and ~ are favorites, if / is used in the pattern), you are looking for 4 digits at the beginning: yyyy/mm/dd. Decide what you're looking for. You might also be able to do something like

[0-9]{4}/[0-9]{2}/[0-9]{2}

or even

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

... I know those will work in Perl, but I haven't tried them with PHP (they ought to work, as the "p" in preg stands for Perl, but no guarantees).

Phil Perry
  • 2,126
  • 14
  • 18
0

Why use regex? Use DateTime class for validation.

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

function

Community
  • 1
  • 1
Glavić
  • 42,781
  • 13
  • 77
  • 107
0

Your code can be rewritten in short like this:

#!/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);
}

The problem was with the missing PCRE regex delimiters as others already pointed out. Even after fixing this, the code was not really nice.

The glob and file_get_contents functions are available as of PHP 4.3.0. The file_put_contents function is available as of PHP 5.

glob makes your code more succinct, readable and even portable as you won‘t have to mention directory separator anywhere except the info message. You used \\ but should have used DIRECTORY_SEPARATOR if you wanted your code to be portable.

The file_get_contents function fetches the whole contents of a file as a string. The file_put_contents function does the opposite – stores a string in a file. If you want it in PHP 4, use this implementation:

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;

Also notice that the final ?> is not necessary in PHP.

Community
  • 1
  • 1
Palec
  • 12,743
  • 8
  • 69
  • 138