How to handle spaces with preg_split in PHP - php

I'm getting a ftp_rawlist of files from FTP in PHP.
I take the rawlist and run this code:
foreach ($ftp_rawlist AS $ff) {
$ff = preg_split("/[\s]+/", $ff, 9);
$perms = $ff[0];
$user = $ff[2];
$group = $ff[3];
$size = $ff[4];
$month = $ff[5];
$day = $ff[6];
$file = $ff[8];
}
This works fine, but if a $ff[8] has a space at the beginning of the file name, my code doesn't parse it to $file.
E.g. " file.pdf" is parsed as "file.pdf"
I'm not sure how to modify my preg_split to capture spaces.

Try this: Remove the + symbol from the regexp by doing:
$ff = preg_split("/[\s]/", $ff, 9);
Cheers.

Related

How can i add a number to a file name in php

Goodevening to everyone, how can i add a number to a file name in php.
Let me explain; I want to save a file using a dropzone but i want to rename the file if it exist in the folder.
I've written down this code but the regex doesn't work and also if it's possible to insert the number before the extension of the file like google chrome does.
if(file_exists($target_file)){
if(preg_match_all($target_file, "'('[0-9]{1,}')'")==false){
$target_file= $target_path."(1)".$name;
}else{
$pos=preg_match_all($target_file, "'('[0-9]{1,}')'");
$pos=$pos++;
$pos1=strpos($pos, $target_file, ")");
$pos1=$pos1-$pos;
$num=substr($target_file, $pos, $pos1);
$num = (int)$num;
$num =$num++;
$sostituisci="(".$num.")";
$target_file=preg_replace("'('[0-9]{1,}')'", $sostituisci, $target_file);
}
}
$name is the name of the file i want to save with the extension
the first $target_file of the code contain the full path + the name of the file
$target_file is a sting like /dropzone/upload/filename.txt and $name is a string like filename.txt. If the $targetfile exist i would to rename the $name like filename(1).txt or filename(2).txt and so on
also other solutions are accepted like a js library.
I assume you are referring to this set of code here.
if(preg_match_all($target_file, "'('[0-9]{1,}')'")==false){
$target_file= $target_path."(1)".$name;
}
insert the number before the extension of the file
EDIT: Use explode() and re-format the ext.
EXAMPLE:
$target_path = "/assets/imgages/";
$name = 'img.jpg';
$name = explode('.', $name);
$format = $name[0].'(1).'.$name[1];
$path = $target_path.$format;
Will produce the following string:
/assets/img/notes(1).txt
Accept multiple dots in string.
$filename = 'company.jobtitle.field.text';
function formatDuplicateExtension($filename){
$stmt = NULL;
$format = explode('.', $filename);
$i = 0;
foreach($format as $key => $value){
if($value === end($format)){
$stmt .= '(1).'.$format[$i];
}elseif($key === count($format)-2){
$stmt .= $format[$i];
}else{
$stmt .= $format[$i].'.';
}
$i++;
}
return $stmt;
}
echo formatDuplicateExtension($filename);
$filename = 'company.jobtitle.field.text';
OUTPUTS: //-->/assets/imgages/company.jobtitle.field(1).text
$name = 'trees.vac2012.img.jpg';
OUTPUTS: //--> /assets/imgages/trees.vac2012.img(1).jpg
I've found a solution idk if it's the best one because regex searches and substitutions are involved a lot of times and it seems to be they're resources consuming functions.
//this function insert the $number in the name of the file before .extension
function InsertBeforeExtension($filename,$number){
$stmt = NULL;
$format = explode('.', $filename);
$i = 0;
foreach($format as $key => $value){
if($value === end($format)){
$stmt .= '('.$number.').'.$format[$i];
}elseif($key === count($format)-2){
$stmt .= $format[$i];
}else{
$stmt .= $format[$i].'.';
}
$i++;
}
return $stmt;
}
//this function check if there's a string like (number).ext in the name
//if yes increment the (number) in the string that become (number++).ext
//if no insert (1) before .ext
function insertnumber($string){
$matches=array();
$re = '/[(][0-9]+[)]\.[a-zA-Z]+/m';
preg_match_all($re, $string, $matches, PREG_SET_ORDER, 0);
if($matches[0][0]){
//if (number).ext is present
$re = '/[(][0-9]+[)]/m';
$str = $matches[0][0];
//select the (number) only
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
//remove parethesis
$str=substr($matches[0][0],1,-1);
//cast sting to an int for add a number
$int = (int)$str;
$int++;
//replace the last (number) match in the name of the file with (number++)
$re = '/(.*)[(][0-9]+[)]/m';
$subst = '${1}('.$int.')';
$result = preg_replace($re, $subst, $string);
}else{
//if (number).ext is not present insert (1) before .ext
$result=InsertBeforeExtension($string,1);
}
return $result;
};
$target_file = $target_path.$name;
//If the file exist repeat to find the number of file that doesn't exist
if( file_exists( $target_file )) {
while(file_exists( $target_file )){
$name=insertnumber($name);
$target_file = $target_path.$name;
}
}
The only problem is that if you have uploaded a file named like file(3).txt and you upload another file with the same name this function rename it in file(4).txt and not in file(3)(1).txt but for my scope this is not important
I've commented the code trying to be the most clear possible this solution seems to work well but i've not calculate the performance.

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

Scan special string using sscanf

I want for example to scan this $lang['foo1']='foo2'; from a PHP file so I tried
this but it doesn't work.
$file = "../lang/lang.en.php";
if(file_exists($file)) {
$text = fopen($file, 'r+');
$content = trim(file_get_contents($file, NULL, NULL, 221));
$i = 0;
do {
$n = sscanf($content, "\$lang['%s']=%s;", $s1[$i], $s2[$i]);
echo $s1[$i].'==>'.$s2[$i];
$i++;
} while($s1[$i]! = '' && $s2[$i] != '');
}
What is my problem?
You should just include('../lang/lang.en.php') like a normal PHP file.
Also, it's possible to make lang.en.php return an array directly with return, http://nl3.php.net/manual/en/function.return.php
I would recommend to use preg_match_all() in your case.
// Match
// $lang['PAGE_TITLE']='Meine Webseite Titel';
$content = file_get_contents('../lang/lang.en.php');
preg_match_all("~\$lang\['.+'\]\s=\s'.+';~", $content, $result);
var_dump($result);

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

php turn line break into semicolon

I have a csv file with this:
software
hardware
educational
games
languages
.
.
.
I need a new csv file with:
software;hardware;educational;games;languages;....
How can I do that?
I'm doing:
<?php
$one = file_get_contents('one.csv');
$patterns =" /\\n/";
$replacements = ";";
$newone = preg_replace($patterns, $replacements, $one);
echo $newone;
file_put_contents('newone.csv', $newone );
?>
This adds the semicolon at the end of the line but the line break is still there
Surprisingly none of you mentioned file() that returns what he needs:
$cont = file('somefile.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
file_put_contents('somefile.csv',implode(';',$cont));
2 lines of code without using slow regex
OR
if you need less code, here with 1 line of code, the way i like !
file_put_contents(
'somefile.csv',
implode(
';',
file('somefile.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
)
);
Here is how you can do this.
Edit : tested this, works correct.
<?php
$row = 1;
$readHandle = fopen("in.csv", "r"); // open the csv file
$writeHandle = fopen("out.csv","w");
$subArr = array();
while (($data = fgetcsv($readHandle, 1000, "\n")) !== FALSE) {
$myStr = $data[0]; // this stores the zeroth column of each CSV row
$subArr[] = $myStr; // subArr contains all your words
}
fputcsv($writeHandle,$subArr,";"); // it creates a CSV with single line seperated by ;
fclose($readHandle);
fclose($writeHandle);
?>
I guess you could get a preg_match_all() to get every alphanumeric word surrounded by quotes into an array.
Then you just loop on that array and display them adding a semicolon.
as a one off, I would run home to mama...
perl -p -i -e 's|(.*)\n|$1;|m' one.cvs
Your file may have carriage returns. Try this:
$newone = str_replace("\r\n", ';', $one);
To cover all possibilities:
<?php
$file = 'data.csv';
file_put_contents($file, '"software"
"hardware"
"educational"
"games"
"languages"
');
$input_lines = file($file);
$output_columns = array();
foreach($input_lines as $line){
$line = trim($line); // Remove trailing new line
$line = substr($line, 1); // Remove leading quote
$line = substr($line, 0, -1); // Remove trailing quote
$output_columns[] = $line;
}
echo implode(';', $output_columns);
Beware: this code assumes no errors in input file. Always add some validation.
I suggest doing it like this:
<?php
$one = file_get_contents('one.csv');
$patterns ="/\\r?\\n/";
$replacements = ";";
$newone = preg_replace($patterns, $replacements, $one);
echo $newone;
file_put_contents('newone.csv', $newone );
?

Categories