Conditional regex php - php

I'm facing some problem with php regex but after many researches (conditional regex, subpattern regex), I still can't solve it.
I have a folder that contains many images and based on variable value I have to go to that folder and select all images that match the value.
e.g: In my folder I have 3 images:
p102.jpg ; p1020.jpg ; p102_1.jpg;
I only want the regex to select :
p102.jpg ; p102_1.jpg
but with the regex below It selects all 3 images.
$image_to_find = 102;
$path = "[^\d]*.*/"
$test = "/^[a-zA-Z]?$image_to_find".$path;
foreach(glob($file_directory) as $file){
if(preg_match($test, $file)){
match[]= $file;
}
}
I also try:
$path = "(?:\_[0-9]?).*/"; (it selects only p102_1.jpg)
Can you help me to figure it out. thanks
(sorry for the english)

You can avoid the foreach loop if you use the glob pattern:
$num = 102;
$result = glob($path . '[a-zA-Z]' . $num . '[._]*');
Note: if you need to allow several different formats, you can use array_merge and several glob patterns: array_merge(glob(...), glob(...));
If you want the first letter optional:
$result = array_merge(
glob($path . $num . '[._]*jpg'),
glob($path . '[a-zA-Z]' . $num . '[._]*jpg')
);
or better, use the brace option:
$result = glob($path . '{[a-zA-Z],}' . $num . '[._]*jpg', GLOB_BRACE);
That stays a better alternative than the combo "foreach/preg_match" (or preg_grep) if filenames are not too complicated.
With preg_grep:
$pattern = '~(?:^|/)[a-z]?' . $num . '(?:_\d+)?\.jpg$~i';
$result = preg_grep($pattern, glob($path . '*' . $num . '*.jpg'));

Try this:
/p102[_\.]\d*\.?jpg/g
https://regex101.com/r/hM4oE0/1
Where p102 should be your 'image_to_find' var.

Not tested, should work.
$find = 102;
$pattern = "/p". $find ."(?:_\d+)?\.jpg/";
$list = array();
foreach (glob($file_directory) as $file)
{
if (preg_match($pattern, $file))
{
$list[] = $file;
}
}
regex: http://regexr.com/3bp29

Tested and working:
<?php
$image_to_find = 102;
$pattern = '[a-zA-Z]' . $image_to_find . '[._]*';
$path = '/your_folder/your_subfolder/';
$file_directory = glob($path . $pattern );
echo '<pre>';
var_dump($file_directory);
echo '</pre>';
exit();
I hope this helps!

Related

I need to check if certain number is in string of numbers

I really need some help with this... i just cant make it work.
For now i have this piece of code and it's working fine.
What it does is... retuns all files within a directory according to date in their name.
<?php
header('Access-Control-Allow-Origin: *');
$imagesDir = '';
$images = glob($imagesDir . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
$filteredImages = [];
foreach($images as $image) {
$current_date = date("Ymd");
$file_date = substr($image, 0, 8);
if (strcmp($current_date, $file_date)>=0)
$filteredImages[] = $image;
}
echo json_encode($filteredImages, JSON_UNESCAPED_UNICODE);
?>
But now i need to filter those files (probably before this code is even executed). acording to the string in their name.
files are named in the following manner:
yyyymmdd_xxxxxxx-xxxxxx~yyyymmdd.123456789.jpg
yyyymmdd_xxxxxxx-xxxxxx~yyyymmdd.9.jpg
yyyymmdd_xxxxxxx-xxxxxx~yyyymmdd.458.jpg
i need to filter out only ones that have certain number within that string of numbers at the end (between "." and ".jpg") eg. number 9
$number = 9
i was trying with this piece of code to seperate only that last part of name:
<?php
function getBetween($jpgname,$start,$end){
$r = explode($start, $jpgname);
if (isset($r[1])){
$r = explode($end, $r[1]);
return $r[0];
}
return '';
}
$jpgname = "yyyymmdd_xxxxxxx-xxxxxx~yyyymmdd.12789.jpg";
$start = ".";
$end = ".jpg";
$output = getBetween($jpgname,$start,$end);
echo $output;
?>
and i guess i would need STRIPOS within all of this... but im lost now... :(
You can probably use preg_grep.
It's regex for arrays.
This is untested but I think it should work.
header('Access-Control-Allow-Origin: *');
$imagesDir = '';
$images = glob($imagesDir . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
$find = 9;
$filtered = preg_grep("/.*?\.\d*" . $find . "\d*\./", $images);
The regex will look for anything to a dot then any number or no number, the $find then any or no number again and a dot again.
Is this what you need ? It will give you 123456789
$string = "yyyymmdd_xxxxxxx-xxxxxx~yyyymmdd.123456789.jpg";
$explode = explode(".", $string);
echo ($explode[1]);
Edit -
As per your requirement Andreas's solution seems to be working.
This is what I tried , I changed the find variable and checked.
$images = array("yyyymmdd_xxxxxxx-xxxxxx~yyyymmdd.12789.jpg");
$find = 32;
$filtered = preg_grep("/.*?." . $find . "./", $images);
print_r($filtered);

Removing some strings in a word in PHP within an array

I am have retrieved all the file contents from a directory. It prints the file contents name from an array. However I want only a portion of the file content name. Any idea how can I achieve this? I have tried using the following:
The file contents from the directory has format: pdb101m.ent.gz , pdb102l.ent.gz
I want to retrieve only the 101m and 102l
<?php
$dir = "C:/Users/Desktop/EAD/PDB/";
$files = array();
$dh = opendir($dir);
while (false !== ($filename = readdir($dh))) {
$files[] = $filename;
}
foreach($files as $ex){
echo str_replace('pdb.ent.gz', ' ', $ex). '<br>';
}
?>
Please help. Grateful.
Use substr() function:
echo substr('pdb101m.ent.gz',3,4); // Outputs: 101m
echo substr('pdb102l.ent.gz',3,4); // Outputs: 102l
So:
foreach($files as $ex){
echo substr($ex, 3,4). '<br>';
}
Edit: Update my answer attending the OP new request:
So in your query you should use:
foreach ($files as $ex) {
$search = substr($ex, 3, 4);
$sql = 'SELECT DISTINCT `pdb_code` FROM pdb WHERE `pdb_code` <> "' . $search . '" LIMIT 6';
$result = mysql_query($sql) or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
$pdb[] = $row['pdb_code'];
}
}
If it's always pdb at the beggining and .ent.gz at the end you can do simply:
echo substr('pdb101m.ent.gz',3,-7);
Negative value of third parameter in substr() means
that many characters will be omitted from the end of string

Function for each subfolder in PHP

I am new in PHP and can't figure out how to do this:
$link = 'http://www.domainname.com/folder1/folder2/folder3/folder4';
$domain_and_slash = http://www.domainname.com . '/';
$address_without_site_url = str_replace($domain_and_slash, '', $link);
foreach ($folder_adress) {
// function here for example
echo $folder_adress;
}
I can't figure out how to get the $folder_adress.
In the case above I want the function to echo these four:
folder1
folder1/folder2
folder1/folder2/folder3
folder1/folder2/folder3/folder4
The $link will have different amount of subfolders...
This gets you there. Some things you might explore more: explode, parse_url, trim. Taking a look at the docs of there functions gets you a better understanding how to handle url's and how the code below works.
$link = 'http://www.domainname.com/folder1/folder2/folder3/folder4';
$parts = parse_url($link);
$pathParts = explode('/', trim($parts['path'], '/'));
$buffer = "";
foreach ($pathParts as $part) {
$buffer .= $part.'/';
echo $buffer . PHP_EOL;
}
/*
Output:
folder1/
folder1/folder2/
folder1/folder2/folder3/
folder1/folder2/folder3/folder4/
*/
You should have a look on explode() function
array explode ( string $delimiter , string $string [, int $limit ] )
Returns an array of strings, each of
which is a substring of string formed
by splitting it on boundaries formed
by the string delimiter.
Use / as the delimiter.
This is what you are looking for:
$link = 'http://www.domainname.com/folder1/folder2/folder3/folder4';
$domain_and_slash = 'http://www.domainname.com' . '/';
$address_without_site_url = str_replace($domain_and_slash, '', $link);
// this splits the string into an array
$address_without_site_url_array = explode('/', $address_without_site_url);
$folder_adress = '';
// now we loop through the array we have and append each item to the string $folder_adress
foreach ($address_without_site_url_array as $item) {
// function here for example
$folder_adress .= $item.'/';
echo $folder_adress;
}
Hope that helps.
Try this:
$parts = explode("/", "folder1/folder2/folder3/folder4");
$base = "";
for($i=0;$i<count($parts);$i++){
$base .= ($base ? "/" : "") . $parts[$i];
echo $base . "<br/>";
}
I would use preg_match() for regular expression method:
$m = preg_match('%http://([.+?])/([.+?])/([.+?])/([.+?])/([.+?])/?%',$link)
// $m[1]: domain.ext
// $m[2]: folder1
// $m[3]: folder2
// $m[4]: folder3
// $m[5]: folder4
1) List approach: use split to get an array of folders, then concatenate them in a loop.
2) String approach: use strpos with an offset parameter which changes from 0 to 1 + last position where a slash was found, then use substr to extract the part of the folder string.
EDIT:
<?php
$folders = 'folder1/folder2/folder3/folder4';
function fn($folder) {
echo $folder, "\n";
}
echo "\narray approach\n";
$folder_array = split('/', $folders);
foreach ($folder_array as $folder) {
if ($result != '')
$result .= '/';
$result .= $folder;
fn($result);
}
echo "\nstring approach\n";
$pos = 0;
while ($pos = strpos($folders, '/', $pos)) {
fn(substr($folders, 0, $pos++));
}
fn($folders);
?>
If I had time, I could do a cleaner job. But this works and gets across come ideas: http://codepad.org/ITJVCccT
Use parse_url, trim, explode, array_pop, and implode

proper usage of glob()

Is this the correct way to us glob() i'm trying to do a case insensitive search for the folder TestFolder on the server.
$chid = "testFoLdER";
$dirchk2 = "/temp/files/" . glob('".$chid."') . "/" . $data[1] . ".doc";
#code_burgar I made these changes to apply to the example code_burgar showed me. is this correct?
what i'm trying to do here is what ever globistr find for casing, rename the folder to lowercase.
$chid = (strtolower($_POST['chid']));
$findbatch = globistr($chid);
$results = glob($findbatch);
if ( !empty($results) ) {
$result = $results[0];
rename("/temp/files/" . $results . "/", "/temp/files/" . strtolower($chid) . "/");
}
else
{
$missing_dir = 'Folder containing files, Not Found: ' . $chid . "\r";
$errfile = fopen("/rec/" . $chid . "-errlog.txt", "a");
fwrite($errfile, $missing_dir . "\n");
fclose($errfile);
exit();
}
That is most definitely not the way to use glob(). glob() returns an array and you are trying to use it in string concatenation.
As Pekka pointed out, PHP man page for glob has some case-insensitive example code.
What you are looking for basically is something along these lines (globistr() comes from PHP man page comments):
$chid = globistr("testFoLdER");
$results = glob($chid);
if ( !empty($results) ) {
$result = $results[0];
$dirchk2 = "/temp/files/" . $result . "/" . $data[1] . ".doc";
} else {
echo('Not found');
}
As workaround you can search all folder inside /temp/files/ that contain $data[1]. '.doc' file and then loop through results to make case-insensitive check if path contains your folder.
$file = "/temp/files/*/".$data[1].".doc";
$locations = glob($file);
$found = false;
foreach($locations as $l){
if(stripos($l,'/testfolder/') !== false){
$found = $l;
break;
}
}

Growing a list of links from a query

I have the following code, which will retrieve a filename from a table and make a link to it. What I want to do, is have it so I can refer to $filesList later on, and it will contain a single block of html code with links to as many files as there are files.
I thought adding to the previous variable would be the easiest way to do this, but it actually outputs nonsense code: 0test.sh">test.sh
if ($getFiles = $con->prepare($filesQuery)) {
$getFiles->bind_param("s", $pk);
$getFiles->execute();
$getFiles->bind_result($FILENAME);
$files = array();
while ($getFiles->fetch()) {
$filename = array(
'FILENAME' => $FILENAME,
);
$files[] = $filename;
}
}
$filesList = '';
foreach ($files as $filenames)
{
$filesList = $filesList + '<p>'. $filenames['FILENAME'] .'' . "\n";
};
Sureley I do not need to have an array for what i want to do?
You need to change that code to:
$filesList = '';
foreach ($files as $filenames)
{
$filesList .= '<p>'. $filenames['FILENAME'] ."</p>\n";
};
Does that help? You cannot concatenate with +.
One thing that I immediately spot is that you have $filesList = $filesList + ... Use a dot and not a + -sign.
Try this
$filesList = $filesList . "<p>{$filenames['FILENAME']}";
Have you tried something like this?
(Untested code, as I am not at home)
if ($getFiles = $con->prepare($filesQuery)) {
$getFiles->bind_param("s", $pk);
$getFiles->execute();
$getFiles->bind_result($FILENAME);
$files = array();
while ($getFiles->fetch()) {
$filesList = $filesList + '<p>'. $FILENAME .'' . "\n";
}

Categories