Multiple calls to preg_replace alters result - php

I have a bunch of files that were named in a somewhat standard format. The standard form is basically this:
[integer]_word1_word2_word3_ ... _wordn where a word could really be anything, but all words are separated by an underscore.
There is really only 3 things I want to do to the text:
1.) I want to modify the integer, which is always at the beginning, so that something like "200" would become $ 200.00.
2.) replace any "words" of the form "with", "With", "w/", or "W/" with "with".
3.) Replace all underscores with a space.
I wrote three different preg_replace calls to do the trick. They are as follows:
1.) $filename = preg_replace("/(^[0-9]+)/","$ $1.00",$filename)
2.) $filename = preg_replace("/_([wW]|[wW]ith)_/"," with ",$filename)
3.) $filename = preg_replace("/_/"," ",$filename);
Each replacement works as expected when run individually, but when all three are run, the 2nd replacement is ignored. Why would something like that occur?
Thanks for the help!
Update:
Here's the actual code I'm working with:
$path = "./img";
$dir_handle = #opendir($path);
while ($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
$id = preg_replace("/\.jpg/","",$file);
$id = preg_replace("/(^[0-9]+)/","$ $1.00", $id);
$id = preg_replace("/_([wW]\/|[wW]ith)_/"," with ", $id);
$id = preg_replace("/_/"," ", $id);
echo "<a href='javascript:show(\"img/$file\")'>$id</a> <br/>";
}
}
closedir($dir_handle);

Something like that could occur if the first replacement removes some text that the second replace matches on. But I don't think that's what is happening here. I think you just have an error in your second replacement. It looks like you are missing the /:
$filename = preg_replace("/_([wW]\/|[wW]ith)_/"," with ", $filename);
After this change it seems to work fine:
$filename = "200_word1_w/_word2";
$filename = preg_replace("/(^[0-9]+)/","$ $1.00", $filename);
$filename = preg_replace("/_([wW]\/|[wW]ith)_/"," with ", $filename);
$filename = preg_replace("/_/"," ", $filename);
print_r($filename);
Result:
$ 200.00 word1 with word2

Related

PHP: How to explode string

I have a variable that stores the location of a temp file:
$file = 'C:\xampp\htdocs\temp\filename.tmp';
How can I explode all this to get filename (without the path and extension)?
Thanks.
Is not the best code but if you confident that this path will be similar and just file name will be different you can use this code:
$str = 'C:\xampp\htdocs\temp\filename.tmp';
$arrayExplode = explode("\\", $str);
$file = $arrayExplode[count($arrayExplode)-1];
$filename = explode('.', $file);
$filename = $filename[0];
echo $filename;
Advice: Watch out on the path contain "n" like the first letter after the backslash. It could destroy your array.
You should use the basename function, it's meant specifically for that.

correct regex date pattern for dd/mm/yyyy

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.
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
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
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.
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).
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
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.

How to remove variable in img src tag?

I have a sample code:
$filename = 'http://thebox.vn/Uploaded/catmy/2013_04_23/couple_t2.jpg?maxwidth=480';
And I using this code to remove variable (maxwidth)
echo preg_replace('/(\?)$/', '', $filename)
=> How to remove variable (maxwidth), how to fix it ?
if you want to get rid of query, just do that:
$filename = 'http://thebox.vn/Uploaded/catmy/2013_04_23/couple_t2.jpg?maxwidth=480';
$parts = explode("?",$filename);
$filename = $parts[0];
You may try this
$filename = 'http://thebox.vn/Uploaded/catmy/2013_04_23/couple_t2.jpg?maxwidth=480';
echo preg_replace("/\?[a-z]+=\d+/", '', $filename);
DEMO.
you could do:
$filename = "http://thebox.vn/Uploaded/catmy/2013_04_23/couple_t2.jpg?maxwidth=480";
$filename = array_shift(explode('?', $filename));
echo $filename;
Your current regular expression says: replace the last character of $filename with the empty string if that last character is the question mark character.
Here is a fixed regular expression that works for your particular example: /\?maxwidth=.*$/
There are many other expressions that could do the job for various circumstances. However, perhaps it would be better to use PHP's parse_url() function to split the URL into its various parts and then just discard the parts that you do not care about and merge back into a string. For example:
$filename = 'http://thebox.vn/Uploaded/catmy/2013_04_23/couple_t2.jpg?maxwidth=480';
// Parse the filename into parts.
$filename_parsed = parse_url( $filename );
// Merge the parsed filename back into a string,
// discarding any irrelevant parts.
$filename_merged = $filename_parsed[ 'scheme' ] . '://' . $filename_parsed[ 'host' ] . $filename_parsed[ 'path' ];
// Prints: http://thebox.vn/Uploaded/catmy/2013_04_23/couple_t2.jpg
echo $filename_merged;

How to divide string in php

How can I add divider ; in the following variable which contains string
I have string like this:
$filename = "a.jpg3c.pngyes.jpg";
I would like to have something like
a.jpg;3c.png;yes.jpg
This string is created when I select multiple files to upload.
Is regex only solution in here?
Regex is not the only solution! Perhaps you can use str_replace() instead of regex.
$filenames = "a.jpg3c.pngyes.jpg";
$img_extensions = array(".png", ".jpg", ".gif");
$semicolon_additions = array(".png;", ".jpg;", ".gif;");
$newfilenames = str_replace($img_extensions, $semicolon_additions, $filenames);
http://php.net/manual/en/function.str-replace.php
Edit: In your particular case, I would add in the semicolon at the end of the filename inside of your loop.
Here is one option using regular expressions:
$filename = "a.jpg3c.pngyes.jpg";
$regex = '/\.(jpg|png|gif)(?!$)/';
$filename = preg_replace($regex, ".$1;", $filename);

Remove all dots in filename except the dot before the file extension

I am trying to sanitize a filename.
I would like to know of a way to remove all decimals from a files name except the last one. I need to keep the last one because the extension follows that.
EXAMPLE:
abc.def.ghij-klmnop.q234.mp3
This file should look like
abcdefghij-klmnopq234.mp3
Some extensions are longer than 3 characters.
You can use a regex with a positive lookahead. Like this:
$withdots = 'abc.def.ghij-klmnop.q234.mp3';
$nodots = preg_replace('/\.(?=.*\.)/', '', $withdots);
After executing the above, $nodots will contain abcdefghij-klmnopq234.mp3. The regular expression is basically saying match all periods that are followed by another period. So the last period won't match. We replace all matches with an empty string, and we're left with the desired result.
That should do it:
$file = 'abc.def.ghij-klmnop.q234.mp3';
$parts = pathinfo($file);
$filename = str_replace('.', '', $parts['filename']).'.'.$parts['extension'];
You could also do this, it should be faster then using pathinfo & str_replace.
$parts = explode('.', 'abc.def.ghij-klmnop.q234.mp3');
$ext = array_pop($parts);
$nodots = implode('', $parts) . '.' . $ext;
Assuming $s is the name of the file.
$s = (($i = strrpos($s, '.')) === false) ? $s :
str_replace('.','',substr($s,0,$i)).substr($s,$i);

Categories