Hy everyone, I'm having trouble with properly nesting while loops to read from 2 arrays.
I have 2 files from which I read the content:
file1: item_list.txt
string1 \n
string2 \n
string3 \n
...
file2: item+info.txt
string3 \t info1 \t info2 \t info3
string1 \t info7 \t info1 \t info4
string5 \t info2 \t info3
string2 \t info2 \t info4 \t info1
(values are separated by new lines and tabs only, I added one space between characters here just to increase readability).
I read from files using fgetcsv() function, and each row from file is stored as an array into a variable $data. I created a while loop with condition (!feof($fp)) to read through the file until the last row. But I can't quite properly nest the second loop.
What I want to do with this:
read the first string found in file1, go to file2 and try to find that string. If there's a match, get the info data for that string (all of the data, or just one, doesn't matter). If there's no match, return message "no match". In either case, once the second loop has done it's thing, I need to read the second string in file1, and do the search in file2 again. Repeat this as long as there is something to read from the file1.
here are two versions of my code, they don't work, and I can't figure out why.
//opening the files
$fp = fopen("$DOCUMENT_ROOT/test/item_list.txt", "r"); #raw item list
$pf = fopen("$DOCUMENT_ROOT/test/item+info.txt", "r"); #item+info list
//read from first file
$line=0;
while (!feof($fp)){
$line++;
$data1 = fgetcsv($fp, "1000", "\n");
$item1= $data1[0];
echo "line: $line. item_list: ".$item1; //just to see on screen what's happening
print_r($data1); //same here, just to see what's going on
echo"<br />";
//searching for string in file2
$row=0;
while (!feof($pf)){
$row++;
$data2 = fgetcsv($pf, "1000", "\t");
$item2= $data2[0];
echo "line: $row. item+info: ".$item2; //just checking things on screen
print_r($data2); //here too
echo "<br />";
//conditioning
//equal strings
if ($string1== $string2)
echo $data2[1]."<br />";
break;
}
}
fclose($fp);
fclose($pf);
this used to work as long as the items in item_list.txt and item+info.txt are oredered
exactly the same (string1\nstring2\string3 ->
string1\tinfo1\nstring2\tinfo2\nstring3\tinfo3 - but that's never going to happen in my
case, it's impossible to order the items like that)
I tried to do it with foreach() statement do itterate through arrays, but the result is something that I can't make any sense out of.
while (!feof($fp)){
$data1 = fgetcsv($fp);
foreach ($data1 as $token1) {
while (!feof($pf)) {
$data2 = fgetcsv($pf);
foreach ($data2 as $value) {
explode ("\t", $value);
if ($token1 == $value[0])
echo $value[1];
}
break;
}
}
}
This should do it:
$file1 = file($DOCUMENT_ROOT . '/test/item_list.txt');
$file2 = file($DOCUMENT_ROOT . '/test/item+info.txt');
foreach ($file1 as $line)
{
$line = rtrim($line); // just in case ...
if ($line === '') continue;
foreach($file2 as $infoline)
{
$infoline = explode("\t", rtrim($infoline);
if ($line === $infoline[0])
{
array_shift($infoline);
echo $line . '<br /><br />' . implode('<br />', $infoline);
// $results[$line] = $infoline; // uncomment this if you need the search results stored for later use
break;
}
}
}
Here's a rough shot at it:
$filename1 = 'item_list.txt';
$filename2 = 'item+info.txt';
# Init the Raw Array
$content2raw = array();
# Get the File Contents for File 2
$file2 = file_get_contents( $filename2 );
# Split it into an Array by Line Breaks
$content2raw = preg_split( "/\n/" , $file2 , -1 , PREG_SPLIT_NO_EMPTY );
# Unset the variable holding the file contents
unset( $file2 );
# Init the Fixed Array
$content2 = array();
# Loop through the Raw Array
foreach( $content2raw as $l ){
// Each Line of Filename2
# Split the Line on Tabs
$t = preg_split( "/\s*\t\s*/" , $l , -1 );
# Set the Fixed Array, using the first element from the line as the key
$content2[ $t[0] ] = $t;
}
# Unset the Raw Array
unset( $content2raw );
# Get the File Contents from File 1
$file1 = file_get_contents( $filename1 );
# Split it into an Array by Line Breaks
$contents1 = preg_split( "/\n/" , $file1 , -1 , PREG_SPLIT_NO_EMPTY );
# Unset the variable holding the file contents
unset( $file1 );
# Loop through the Lines, using each line as the Key to look for
foreach( $content1 as $v ){
# Check whether a matching element exists in the array from File 2
if( !array_key_exists( $k , $content2 ) ){
// No Match Found
echo 'No Match';
}else{
// Match Found
echo 'Match Found';
var_dump( $content2[$v] );
}
}
Amendment, as per comment/feedback from #Bluewind
$filename1 = 'item_list.txt';
$filename2 = 'item+info.txt';
# Open and Split the file into an Array by Line
$content2raw = file( $filename2 );
# Init the Fixed Array
$content2 = array();
# Loop through the Raw Array
foreach( $content2raw as $l ){
// Each Line of Filename2
# Split the Line on Tabs
$t = preg_split( "/\s*\t\s*/" , $l , -1 );
# Set the Fixed Array, using the first element from the line as the key
$content2[ $t[0] ] = $t;
}
# Unset the Raw Array
unset( $content2raw );
# Open and Split the file into an Array by Line
$contents1 = file( $filename1 );
# Loop through the Lines, using each line as the Key to look for
foreach( $content1 as $v ){
# Check whether a matching element exists in the array from File 2
if( !array_key_exists( $k , $content2 ) ){
// No Match Found
echo 'No Match';
}else{
// Match Found
echo 'Match Found';
var_dump( $content2[$v] );
}
}
This is actually much less code than you seem to think. First, you read an info file and build a hash table out of it:
foreach(file("info_list") as $line) {
$line = explode("\t", trim($line));
$info[$line[0]] = $line;
}
then you iterate through the items file and look if there are matching entries in the hash:
foreach(file("item_list") as $line) {
$item = trim($line);
if(isset($info[$item]))
// we have some info for this item
else
// we have no info for this item
}
that's basically all about this
Related
I have this script that reads the last 100 lines from a text file, I explode out each line into 3 chunks were separated by a space. The third chunk of data I want to check to see if it contains a word or phrase from one of the lines in another text file filters.txt. If a match is found, then I want to replace that word or phrase with some formatting so it stands out. Below is what I have but it does not work, the code that checks against the filters has no effect.
Can anyone please show me how I should do this.
Thanks in advance.
Here is a line from sample.log...
12:12:46 18-10-18 #:10656200,1A,29D09 ,RTC NOT ALERT , ,CHEMIST WAREHOUSE , , ,910 David Low Way ,MARCOOLA ,S59K7 , , ,
In the filters.txt file will be lines such as...
RTC
RTC INJURIES
RTC NOT ALERT
RTC HIGH MECH
In above exmaple when I print out the data I want the 'RTC NOT ALERT' to be highlighted so it stands out. So in brief, for every line in sample.log I want to see if any of the filters appear in it, if so I want it to be highlighted on output. I do this by changing the font styling with css.
<?php
// OPEN LOG FILE FOR READING
$file = array_reverse( file( 'sample.log' ));
// OPEN FILTERS LIST
$filters = file( 'filters.txt' );
// START MAIN LOOP (SHOWS LAST X LINES FROM TEXT FILE)
$limit = 100;
for ($i = 0; $i < $limit; $i++ ){
$data = explode(' ', $file[$i],3);
// CHECK FOR FILTERS AND HIGHLIGHT IF MATCHED
foreach ( $filters as $filter ){
if (strpos($data[2], $filter) !== false) {
$data[2] = str_replace($filter,"<font
class=\"highlight\">$filter</font>",$data[2]);
}
}
// PRINT LIST
print "
<div class=\"code1a\">
<font class=\"time\">$data[0] $data[1]</font><br>
$data[2]
</div>
";
}
?>
Though you didn't give any example from sample.log and filters.txt, I think you need to trim each $filter because of line-break.
Try:
<?php
// OPEN LOG FILE FOR READING
$file = array_reverse( file( 'sample.log' ) );
// OPEN FILTERS LIST
$filters = file( 'filters.txt', FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES );
// START MAIN LOOP (SHOWS LAST X LINES FROM TEXT FILE)
$limit = 100;
// BECAUSE $file STARTS WITH 0
$limit -= 1;
foreach ( $file as $line => $line_content ) {
if ( $line == $limit ) {
break;
}
$data = explode( ' ', $line_content, 3 );
$highlight = $data[ 2 ];
// CHECK FOR FILTERS AND HIGHLIGHT IF MATCHED
foreach ( $filters as $filter ) {
if ( strpos( $highlight, ',' . $filter . ' ,' ) !== false ) {
$highlight = str_replace( $filter, '<font class="highlight">' . $filter . '</font>', $highlight );
}
}
// PRINT LIST
echo '<div class="code1a">';
echo '<font class="time">', $data[ 0 ], ' ', $data[ 1 ], '</font>';
echo '<br />';
echo $highlight;
echo '</div>';
}
I need to search a string in .cfg file, and delete the whole line. I'm using file_get_contents to retrieve the the data in .cfg file, and I'm storing it in a variable, searching is good but not knowing how to delete the whole line?
I have a string in following way:
user $username insecure-password $password
I want to search $username and delete the whole line.
Use a little Regex to match the line:
<?php
$file = 'blah
etc
user delboy1978uk insecure-password 123456
etc
etc';
$regex = '#\nuser\s\w+\sinsecure-password\s.+\n#';
preg_match($regex, $file, $matches);
$file = str_replace($matches[0], "\n", $file);
echo $file;
Which outputs:
blah
etc
etc
etc
See it here: https://3v4l.org/BcDWK
With this method you can read each config file line by line search in each line.
$h = fopen('yourfile', 'r') ;
$match = 'username' ;
$output = [] ;
if ($h) {
while (!feof($h)) {
$line = fgets($h);
//your current search function, which search each line
if ( your_search_function($line, $match) === false) {
//array $output will not contain matching lines.
$output[] = $line;
}
}
fclose($h);
//write back to file or do something else with $output
$hw = fopen('yourfile', 'w') ;
if( $hw ) {
foreach( $output as $line ) {
fputs($hw, $line) ;
}
fclose($hw) ;
}
}
i have a big string that has many lines of data as shown below(stream name and stream url). I want to put each line into any array then separate each array value to stream name and stream url then construct corresponding hyperlink for each stream line. could any one show me how this can be done?
Edit:
i put each line in to array but i couldnt split each line in to two parts1! my names array is empty! could any one tell me what is wrong ?
$stream_array = explode( "\n", $file_contents );
$names = array();
foreach( $stream_array as $stream ){
$split = explode( $stream, " " );
array_push( $names, $split[ 0 ] );
};
print_r($stream_array);
print_r($names);
i want to put stream names in to names array and stream urls into foo array after i put each line of $file_contents into an array .
for($i = 0; $i < count($foo[1]); $i++){
?>
<?php echo $i.") "; echo $names[0][$i] ;?> <br />
<?
}//end of for
example of big string that holds list of stream($file_contents):
name1 http://somesite.net/all/name1tv.m3u8
name2 http://somesite.net/all/name2tv.m3u8
name3 http://somesite.net/all/name3tv.m3u8
Its quite easy and there are PHP syntax that does most of it for you like so :-
// Get a file into an array.
// Each line will be added as a new occurance of the $lines array
$lines = file('filename.ext');
foreach ( $lines as $line ) {
list($name, $url) = explode(' ', $line);
echo $name . PHP_EOL;
echo $url . PHP_EOL;
// of course you will probably want to do something different here
// this just shows you whats going on.
}
The result would be :
name1
http://somesite.net/all/name1tv.m3u8
name2
http://somesite.net/all/name2tv.m3u8
name3
http://somesite.net/all/name3tv.m3u8
i solved it :-)
$stream_array = explode( "\n", $file_contents );
$names = array();
foreach( $stream_array as $stream ){
//$split = explode( $stream, " " );
$split = preg_split('/\s+/', $stream);
array_push( $names, $split[ 0 ] );
};
print_r($stream_array);
print_r($names);
Let's say I have this in my text file:
Author:MJMZ
Author URL:http://abc.co
Version: 1.0
How can I get the string "MJMZ" if I look for the string "Author"?
I already tried the solution from another question (Php get value from text file) but with no success.
The problem may be because of the strpos function. In my case, the word "Author" got two. So the strpos function can't solve my problem.
Split each line at the : using explode, then check if the prefix matches what you're searching for:
$lines = file($filename, FILE_IGNORE_NEW_LINES);
foreach($lines as $line) {
list($prefix, $data) = explode(':', $line);
if (trim($prefix) == "Author") {
echo $data;
break;
}
}
Try the following:
$file_contents = file_get_contents('myfilename.ext');
preg_match('/^Author\s*\:\s*([^\r\n]+)/', $file_contents, $matches);
$code = isset($matches[1]) && !empty($matches[1]) ? $matches[1] : 'no-code-found';
echo $code;
Now the $matches variable should contains the MJMZ.
The above, will search for the first instance of the Author:CODE_HERE in your file, and will place the CODE_HERE in the $matches variable.
More specific, the regex. will search for a string that starts with the word Author followed with an optional space \s*, followed by a semicolon character \:, followed by an optional space \s*, followed by one or more characters that it is not a new line [^\r\n]+.
If your file will have dinamically added items, then you can sort it into array.
$content = file_get_contents("myfile.txt");
$line = explode("\n", $content);
$item = new Array();
foreach($line as $l){
$var = explode(":", $l);
$value = "";
for($i=1; $i<sizeof($var); $i++){
$value .= $var[$i];
}
$item[$var[0]] = $value;
}
// Now you can access every single item with his name:
print $item["Author"];
The for loop inside the foreach loop is needed, so you can have multiple ":" in your list. The program will separate name from value at the first ":"
First take lines from file, convert to array then call them by their keys.
$handle = fopen("file.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
$pieces = explode(":", $line);
$array[$pieces[0]] = $pieces[1];
}
} else {
// error opening the file.
}
fclose($handle);
echo $array['Author'];
I'm trying to remove some excessive indention from a string, in this case it's SQL, so it can be put into a log file. So I need the find the smallest amount of indention (aka tabs) and remove it from the front of each line, but the following code ends up printing out exactly the same, any ideas?
In other words, I want to take the following (NOTE: StackOverflow editor converted my tabs to spaces, in the code, a tab simulates 4 spaces, but it really is a \t character)
SELECT
blah
FROM
table
WHERE
id=1
and convert it to
SELECT
blah
FROM
table
WHERE
id=1
here's the code I tried and fails
$sql = '
SELECT
blah
FROM
table
WHERE
id=1
';
// it's most likely idented SQL, remove any idention
$lines = explode("\n", $sql);
$space_count = array();
foreach ( $lines as $line )
{
preg_match('/^(\t+)/', $line, $matches);
$space_count[] = strlen($matches[0]);
}
$min_tab_count = min($space_count);
$place = 0;
foreach ( $lines as $line )
{
$lines[$place] = preg_replace('/^\t{'. $min_tab_count .'}/', '', $line);
$place++;
}
$sql = implode("\n", $lines);
print '<pre>'. $sql .'</pre>';
It seems the problem was
strlen($matches[0])
returns 0 and 1 for the first and last line, which isn't the 3 I actually wanted as the minimum, so a quick hack was to
trim the SQL
skip counting the length if it's less than 2
Not the most elegant solution, but it'll always work because tabs are usually in the 4+ count in this code. Here's the fixed code:
$sql = '
SELECT
blah
FROM
table
WHERE
id=1
';
// it's most likely idented SQL, remove any idention
$lines = explode("\n", $sql);
$space_count = array();
foreach ( $lines as $line )
{
preg_match('/^(\t+)/', $line, $matches);
if ( strlen($matches[0]) > 1 )
{
$space_count[] = strlen($matches[0]);
}
}
$min_tab_count = min($space_count);
$place = 0;
foreach ( $lines as $line )
{
$lines[$place] = preg_replace('/^\t{'. $min_tab_count .'}/', '', $line);
$place++;
}
$sql = implode("\n", $lines);
print $sql;
private function cleanIndentation($str) {
$content = '';
foreach(preg_split("/((\r?\n)|(\r\n?))/", trim($str)) as $line) {
$content .= " " . trim($line) . PHP_EOL;
}
return $content;
}