I have following data extracted from the MySQL database to create labels.
BREAK
Name:RAJ
Company:ABC
Order Number:101
Order Details:
Item1
Item20
Item3
BREAK
Name:RAJ
Company:ABC
Order Number:101
Order Details:
2 x Item1
2 x Item2
2 x Item3
BREAK
Name:RAJ
Company:ABC
Order Number:101
Order Details:
5 x Item4
5 x Item5
5 x Item2
I wrote some code to find the position of BREAK in PHP and it can generate lines number like below.
2
14
26
36
I want a file for the contents that are between line 2 and 14 in one file and 26 to 36 in one file. I am working in php and tried using sed from shell_exec function however if I read this output and generate sed command, I don't get first 2 number together.
What I am expecting is below.
sed -n 2,14p file1.txt
sed -n 26,36p file2.txt
Any suggestion either in php or shell script?
Use array_slice() for getting ranges in an array.
My solution is very hard coupled to your requirements, meaning every first line is a starting range number and the following the end range.
// the lines from which will be read
$lines = "1
5
16
26";
// split these numbers above into an array
$lines = explode(PHP_EOL, $lines);
// the source file where the ranges will be taken off
$file = file('file.txt');
for($i = 0; $i < count($lines); $i+=2) {
$rangeStart = $lines[$i];
$rangeLength = $lines[$i+1] - $lines[$i];
// slice out the ranges, beware the second parameter is the length not the offset!
$ranges[] = array_slice($file, $rangeStart, $rangeLength);
}
print_r($ranges);
But it would be a lot easier to do it automatically on your source file/text/string (?) directly, if this is possible.
$file = file('file.txt');
$len = count($file);
$output = array();
$current = array();
for($i = 0; $i < $len; $i++) {
$data = trim($file[$i]);
if ($data != 'BREAK') {
$current[] = $data;
} else {
$output[] = implode(PHP_EOL, $current);
$current = array();
}
}
print_r($output);
Related
I got help from a group user with the previous question, but instead of reading the lines from a txt file, i want to read the lines of numbers from a string.
1 and until 119
How can this be done?
Through txt file it works:
$lines = file("lines.txt");
if($i==119)
...
through string does not.
$numbers = "1
2
4
5
..."
for($i = 119; $i >= 0; $i--)
{
$lines = "$numbers";
if($i==119)
{
$no_of_lines = round(count($lines)/14);
}
$line = $lines["$i"];
echo "$line<br>";
if( $i % 14 === 0 )
{
echo "$no_of_lines<br>";
$no_of_lines--;
}
}
To access your string you either need to know the position in the string where you could use substr but when your numbers get to 10 and beyond the length of 1 digit you can't know the position of each number.
So you could use explode to create an array called $lines delimited by a space (if all your numbers are separated by a space:-
$lines= explode(" ", $numbers);
so then your code could be :-
<?php
$numbers = "1 2 3 4 5 6";
$lines= explode(" ", $numbers);
for($i = 0; $i < count($lines); $i++) {
$line = $lines[$i];
echo "$line<br>";
}
echo "<br>No_of_lines = " . count($lines);
?>
Which gives as your output :-
1
2
3
4
5
6
No_of_lines = 6
I have a .lst(playlist) file with around 1800 lines of data. Each line contains a URL to an audio file that is being played on my radio station.
The thing is I need to add URLs to some Advertisements after every 'n' number of lines in that file.
There are 10 URLs of advertisements from which 1 URL needs to be added after every 5 lines.
Example: URLs of Advertisements are in this format: file1.mp3, file2.mp3 ... file10.mp3
They will be added like this: file1.mp3 on line 5, file2.mp3 on line 10, file3.mp3 on line 15 and so on. After file10.mp3 has been inserted, it will again start from file1.mp3. I hope you understand.
So far I have managed to cook up the following code, but it only takes up one string to be added and have to manually tell the line number on which the string will be added. Unable to figure out the looping logic to do the aforementioned work.
$url = "/home/station/content/file1.mp3";
$line_number = 5; //add above URL on line number 5
$contents = file('playlist.lst', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if($line_number > sizeof($contents)) {
$line_number = sizeof($contents) + 1;
}
array_splice($contents, $line_number-1, 0, array($url));
$contents = implode("\n", $contents);
file_put_contents('playlist.lst', $contents);
How can I achieve this ?
You can use array_chunk to split your array into $line_number. Then, use array_map() to add your advertisements to each group. Finally, you could reduce to a linear array. You can format the $url using sprintf().
$url = "/home/station/content/file%d.mp3"; // use %d to use using sprintf()
$line_number = 5; //add above URL on line number 5
$counter = 1;
$contents = file('playlist.lst', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// split in group of $line_number
$groups = array_chunk($contents, $line_number);
// for each group:
$groups = array_map(function($arr) use ($url, &$counter) { // pass $counter as reference
// format the link
$adv = sprintf($url, $counter++) ;
// restart to 1 if greater than 10
if ($counter > 10) $counter = 1;
// append to group
$arr[] = $adv;
return $arr ;
},$groups);
// transform to linear array
$contents = array_reduce($groups, 'array_merge', array());
// save new file
file_put_contents('playlist.lst', implode("\n", $contents));
You could do it this way, with a simple loop:
//changing it to a "model" string, we are going to add the correct file number later
$url = "/home/station/content/file";
$contents = file('playlist.lst', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$count = 0;
$AddCount = 1;
//Loop until there is nothing left in our radio list
while ($count < sizeof($contents)) {
//if we have a multiple of 5, we are inserting an ad
if (($count % 5) == 0) {
// to know wich ad to add we use our AddCounter
$tmp = $url . strval($AddCount) . ".mp3";
//As suggested by Justinas, don't forget that each time you had a line you need to also increase the index for the next one using $count%5 to know how many lines you already added
array_splice($contents, $count - 1 + ($count % 5) , 0, array($tmp));
$AddCount += 1;
if ($AddCount > 10)
$AddCount = 1;
}
$count += 1;
}
$contents = implode("\n", $contents);
file_put_contents('playlist.lst', $contents);
This way, you don't even have to handle the advertisements file selection yourself as long as they are all formated like you said.
You should do a loop in such way.
$line_number = 5;
$line_count = 0;
for($i=0; $i < sizeof($contents); $i++)
{
$line_count = $line_count +1; // start with Line 1 that +1
if($line_count == $line_number)
{
// do your magic code of adding a line
$line_count = 0; // refresh counting from the beginning
}
}
You don't need to handle each line in the file one at a time.
Leave the file contents as its original string, inject placeholders with regex, then replace those placeholders with your ad array strings.
Code: (Basic Demo)
$filename = 'playlist.lst';
file_put_contents(
$filename,
vsprintf(
preg_replace(
'/(?:.+(\R)){5}\K/', // match (and forget) 5 lines, capture the newline character
'%s\1', // inject the placeholder following the the newline character
file_get_contents($filename),
count($ads) // make the exact number of needed placeholders
),
$ads // replace the placeholders with the ad strings
)
);
I want to read every 3rd line from file1 and save it as a new file2.
This is what I am trying, but it doesn't work. Any ideas?
$myfile = file("file1.txt");
$lines = file($myFile);
$newFileContent= $lines[2];
file_put_contents("file2.txt", $newFileContent);
So, if file1.txt has the following content:
1
2
3
4
5
6
The file2.txt should contain only:
3
6
The actual easiest way would be to use a normal for loop. The array is non-associative, so it makes no sense to use an expensive foreach over the entire array.
To exactly replicate your sample data, just use something like the following:
$lines = file('file1.txt');
$newContent = '';
$len = count($lines); // saves us from calling count() on every iteration
for ($i = 2; $i < $len; $i += 3) {
$newContent .= $lines[$i];
}
file_put_contents('file2.txt', $newContent);
Working demo
$$I have a bunch fo text files I'd like to eventually explode into arrays, but since the amount of text files is dynamically chosen via user input, I can't just initialize them one-by-one and instead am opting for a for loop.
For the sake of example, three text files I have contain the following (excuse the \n, imagine it's a line break):
file1.txt = 1 \n 2 \n 3
file2.txt = 6 \n 2 \n 7
file3.txt = 9 \n 1 \n 9
The code I attempted:
<?php
for ($i = 1; $i <= 3; $i++) {
list($line1[$i], $line2[$i], $line3[$i]) = file("public_html/texts/file".$i.".txt");
?>
This obviously doesn't work, but I'm not sure why. In the end, the result should be:
$line1[1] = 1
$line2[1] = 2
$line3[1] = 3
$line1[2] = 6
$line2[2] = 2
$line3[2] = 7
$line1[3] = 9
$line2[3] = 1
$line3[3] = 9
How do I go about doing this?
edit; fixed typo.
You have an error in your code, see:
file("public_html/texts/file".&i.".txt");
^-- TYPO HERE
for($i = 1; $i <= 3; $i++) {
$lines = file('public_html/texts/file' . $i . '.txt');
$line1[] = $lines[0];
$line2[] = $lines[1];
$line3[] = $lines[2];
}
I have the following list:
1945/01/05 BA 87 34 1 59 50
1945/01/05 CA 18 17 45 49 82
1945/01/13 BA 6 66 1 16 48
1945/01/13 CA 40 60 32 50 80
and so on....
I want to arrange them as an array like the following:
$array['BA'][0][0] = 87;
$array['BA'][0][1] = 34;
$array['BA'][0][2] = 1;
$array['BA'][0][3] = 59;
$array['BA'][0][4] = 50;
$array['CA'][0][0] = 18;
$array['CA'][0][1] = 17;
$array['CA'][0][2] = 45;
$array['CA'][0][3] = 49;
$array['CA'][0][4] = 82;
$array['BA'][1][0] = 6;
$array['BA'][1][1] = 66;
$array['BA'][1][2] = 1;
$array['BA'][1][3] = 16;
$array['BA'][1][4] = 48;
$array['CA'][1][0] = 48;
$array['CA'][1][1] = 60;
$array['CA'][1][2] = 32;
$array['CA'][1][3] = 50;
$array['CA'][1][4] = 80;
I know that I can use preg_split('/\s+/', $list); to create an array, but how can I create a 3D Array from this list?
Thank you for your help
Try something like this:
Updated the code so you can also load a file since you have memory issues.
Consider: If loading the amount of data already creates memory issues your end result, the array, might also generate memory issues! Since that's even more data!
So this will read per line so it does not load the total file in memory directly. But since you have memory issues you should likely not write to an array but to a database for example. Otherwise the memory issue will keep coming.
<?PHP
/*
* Example when small amount of data is in a string
*/
/*
//your input
$str='1945/01/05 BA 87 34 1 59 50
1945/01/05 CA 18 17 45 49 82
1945/01/13 BA 6 66 1 16 48
1945/01/13 CA 40 60 32 50 80';
//we work per line
$lines=explode("\n", $str);
//loop each line
foreach($lines AS $line) {
*/
/*
* Example when big amount of data is in a file
*/
//this will contain the end result
$result=array();
$filename='lines.txt'; //contains the data like in your question
$fp = fopen($filename,'r');
while($line=fgets($fp)) {
//explode each line on space so we get the different fields
$fields=explode(' ', $line);
//we remove the date, not needed
unset($fields[0]);
//we get the key (BA/CA/etc) and remove it also
$key=$fields[1];
unset($fields[1]);
//we write the result to the array
//using array_values so the indexes are from 0-4 again
//because we removed items
$result[$key][]=array_values($fields);
}
fclose($fp);
//show the result in html
echo '<pre>';
print_r($result);
THE QUESTION CHANGED
This does answer the question asked in the comments, not the actual question.
<?PHP
/*
* Example when big amount of data is in a file
*/
//this will contain the end result
$result=array();
$filename='lines.txt'; //contains the data like in your question
$fp = fopen($filename,'r');
while($line=fgets($fp)) {
//explode each line on space so we get the different fields
$fields=explode(' ', $line);
//we remove the date, not needed
unset($fields[0]);
//we get the key (BA/CA/etc) and remove it also
$key=$fields[1];
unset($fields[1]);
//We start counting the numbers
foreach($fields AS $nr) {
$nr=trim($nr);
if(empty($result[$key][$nr])) {
$result[$key][$nr]=1;
}else{
$result[$key][$nr]++;
}
}
}
fclose($fp);
//show the result in html
echo '<pre>';
print_r($result);
<?php
$a = '1945/01/05 BA 87 34 1 59 50
1945/01/05 CA 18 17 45 49 82
1945/01/13 BA 6 66 1 16 48
1945/01/13 CA 40 60 32 50 80';
$array = array();
$list = explode("\n", $a);
echo '<pre>';
print_r($list);
echo '</pre>';
$first_index = 0;
$counter = 0;
foreach($list as $key=>$value) {
if($counter >=2) {
$first_index++;
$counter= 0;
}
$row = explode(" ",$value);
$k = $row[1];
for($i=2; $i< count($row); $i++) {
$array[$k][$first_index][] = $row[$i];
}
$counter++;
}
echo '<pre>';
print_r($array);
echo '</pre>';
?>