I've got a piece of code searching a text file for an email address, returning the two numbers on the same line.
The file looks like:
24/08/2017,email#test.ie,1,2
21/05/2018,test#234.com,1,2
21/05/2018,test#test.ie,2,2
My code currently looks like
$lines = file("log.txt");
$found = 0;
foreach ($lines as $line){
if (strpos($line, $email) !==false){
$found = true;
$arrayOfLine = explode(",", $line);
$foundGroup = $arrayOfLine[2];
$foundVideo = $arrayOfLine[3];
}
elseif (strpos($line, $email) ===false){
$found = false;
}
}
When I run this code, through a HTML form that takes in the email address to be searched for, it only finds matching emails if they were the last entered - in my example above, test#234.com wouldn't return a match, but test#test.ie would. What am I missing that's preventing it from turning up matches?
You are not terminating your loop when you find an answer, meaning it continues to run even if it found a match and overwrites any previous match. Add a break; after you assigned $foundGroup and $foundVideo.
You also have two evaluations checking the same thing. Set the $found flag to false at the start of the loop. If your loop fails to find a match, it'll still be false. You don't need to compare twice.
$found = false;
foreach ($lines as $line){
if (strpos($line, $email) !==false){
$found = true;
$arrayOfLine = explode(",", $line);
$foundGroup = $arrayOfLine[2];
$foundVideo = $arrayOfLine[3];
break; // stop searching for more matches
}
}
This is actually pretty easy to figure out.
it only finds matching emails if they were the last entered
This is true. Why? Because you always set $found to false, unless the email address you're searching for is the last one. Even if you have found a match, you're just continuing the loop and overwriting $found with false.
Take a look at this snippet and see if you can figure it out.
You either need to break out of the loop, or stop setting $found this way.
foreach ($lines as $line){
if (strpos($line, $email) !==false) {
$found = true;
$arrayOfLine = explode(",", $line);
$foundGroup = $arrayOfLine[2];
$foundVideo = $arrayOfLine[3];
}
elseif (strpos($line, $email) ===false) {
$found = false; // This will be run every loop!
}
}
Related
im trying to check if two php-values are in one line in the csv fiel.
csv:
password, name
12345, max
44444, emil
but when my variable is $password="123" and in the csv file its "12345" he accepts it.
But, how can i check if its 100% equals? I dont understand why "123" is enough?
$search = $name;
$search2 = $password;
$lines = file('Benutzer.csv');
$line_number = false;
$line_number2 = false;
while (list($key, $line) = each($lines) and !$line_number) {
$line_number = (strpos($line, $search) !== FALSE );
$line_number2 = (strpos($line, $search2) !== FALSE );
}
if($line_number and $line_number2 ){
header('Location: alert_anmelden_erfolgreich.php');
}
else{
header('Location: alert_anmelden_NICHT_erfolgreich.php');
}
strpos looks for a substring in a string. So first things first"
strpos('12345','345')
will return 2 since the substring exists starting at that index. In your case:
strpos('12345','123')
or really 1,12,123,1234,12345 will all return the position 0. Now, when equating as you do to false you're essentially getting:
0==`false`
which is of course true because 0 an be casted to false. As #u_mulder, commented use of the full type equality operator === would fix that, but still won't solve your problem!. What you want is strcmp, which will return 0(false) only if the strings are identical, and can be used like you wanted. You could also use === or == between the strings since you don't care about 'less/more' string.
if( $line === $search )
I want to check if a string contains two specific words.
For example:
I need to check if the string contains "MAN" & "WAN" in a sentence like "MAN live in WAN" and returns true else false.
What I've tried is looping string function in a conditional way:-
<?php
$data = array("MAN","WAN");
$checkExists = $this->checkInSentence($data);
function checkInSentence( $data ){
$response = TRUE;
foreach ($data as $value) {
if (strpos($string, $word) === FALSE) {
return FALSE;
}
}
return $response;
}
?>
Is it the right method or do I've to change it? How to implement this any suggestions or idea will be highly appreciated.
Note: data array may contain more than two words may be. I just need check whether a set of words are exists in a paragraph or sentence.
Thanks in advance !
It's alsmost good. You need to make it set the response to false if a word is not included. Right now it'll always give true.
if (strpos($string, $word) === FALSE) {
$response = FALSE;
}
Try this:
preg_match_all("(".preg_quote($string1).".*?".preg_quote($string2).")s",$data,$matches);
This also should work!
$count = count($data);
$i = 0;
foreach ($data as $value) {
if (strpos($string, $value) === FALSE) {
#$response = TRUE; // This is subject to change so not reliable
$i++;
}
}
if($i<$data)
response = FALSE;
I have two files with same format where one has new updates and the other has older updates. There is no particular unique id column.
How can I extract the new updated lines only (with unix, PHP, AWK)?
You want to "byte" compare all lines against the other lines, so i would do:
$lines1 = file('file1.txt');
$lines2 = file('file2.txt');
$lookup = array();
foreach($lines1 as $line) {
$key = crc32($line);
if (!isset($lookup[$key])) $lookup[$key] = array();
$lookup[$key][] = $line;
}
foreach($lines2 as $line) {
$key = crc32($line);
$found = false;
if (isset($lookup[$key])) {
foreach($lookup[$key] as $lookupLine) {
if (strcmp($lookupLine, $line) == 0) {
$found = true;
break;
}
}
}
// check if not found
if (!$found) {
// output to file or do something
}
}
Note that if the files are very large this will consume quite some memory and you need to use some other mechanism, but the idea stays the same
I was wondering how to do it, this code will as you know get specific line, now I need it to read until a specific text like 55 and stops reading from there. As you can see the log contains some whitespace so what function can I use to read until the code 55?
$row['MtID'] = A unique ID to specify the line where the result is.
So for example the log of the result will be
MM3,67624563 (Unique ID (MtID),233262345599,http://mywebsite.com:8080/web/mm3_pixel.php?sspdata=ams1CIv44qa26LGkchACGKqShLrCtZieSyINNDEuMTkwLjg4LjIwOCgB&vurlid=993211,http://mywebsite.net/sspx?id=69171&sspdata=ams1CIv44qa26LGkchACGKqShLrCtZieSyINNDEuMTkwLjg4LjIwOCgB >> OK
,55
$logfile = file("https://myweb.com/Pixel-Full.php?file=".$country."/".$today."-pixel-response.log");
foreach($logfile as $line_num = > $line) {
if (strpos($line, $row['MtID']) !== false) {
$getresult = strstr(htmlspecialchars($line), 'http://');
echo "<td>".$getresult."</td>";
}
}
This system goes like this, a user request something and nothing found, so on our log, it will post the error link requested by user and the error code for us to know what problem it was. So once the system reads the line and continue to read other line as well until it found the code, it stops
$startline = count($logfile)+1;
foreach($logfile as $line_num => $line) {
if (strpos($line, $row['MtID']) !== false) {
$startline = $line_num;
$getresult = trim(strstr(htmlspecialchars($line), 'http://'));
if (strpos($getresult, ",55") !== false) {
$getresult = substr($getresult,0,strpos($getresult, ",55")+3);
break;
}
}
if ($line_num > $startline) {
$getresult .= trim(htmlspecialchars($line));
if (strpos($getresult, ",55") !== false) {
$getresult = substr($getresult,0,strpos($getresult, ",55")+3);
break;
}
}
}
echo "<td>".$getresult."</td>";
You can use the FILE_SKIP_EMPTY_LINES flag in the file call to skip empty lines and then use array_slice to get the part of the array you need.
$file = array_slice(file("https://myweb.com/Pixel-Full.php?file={$country}/{$today}-pixel-response.log", FILE_SKIP_EMPTY_LINES), 0, $row['MtID']);
foreach($file as $line) {
$result = strstr(htmlspecialchars($line), 'http://');
echo "<td>{$result}</td>";
}
It looks like stopping the execution when a positive match is the biggest trick here. This can be done with a break. (http://php.net/manual/en/control-structures.break.php)
//get the file as a string
$logfile = file_get_contents("https://myweb.com/Pixel-Full.php?file=".$country."/".$today."-pixel-response.log", false);
//make up some rows and catch the false
if ($logfile !== false) {
$logrows = explode("\n", $logfile);
//loop
foreach($logrows as $line) {
if (strpos($line, $row['MtID']) !== false) {
$getresult = strstr(htmlspecialchars($line), 'http://');
echo "<td>".$getresult."</td>";
break;
}
}
}
else echo "Log resource unavailable";
//some memory clearing
unset($logfile);
unset($logrows);
I would suggest for matching sanity that you make sure that the logging format makes the MtID variable something that wouldn't be found in the log text unless its a positive match. Using a UUID or a specific ID format would work.
As you regarded, sometimes, the log line may be divided into three lines while in some other times it is only one line:
// Three lines
http://www.yourwebsite.com/error/33/happycodingneverending&errorcode=33,
succcess=false;
,55
// one line
http://www.yourwebsite.com/error/33/happycodingneverending&errorcode=33,succcess=false;,55
In this case you just have to made a little modification to your code, which, works perfect with only one line example to works with that three lines as follows:
foreach($logfile as $line_num = > $line) {
if (strpos($line, $row['MtID']) !== false) {
$getresult = strstr(htmlspecialchars($line), 'http://');
if(!$getresult){
$theExactLine = $line_num - 2;
$getresult = $logfile[$theExactLine];
}
echo "<td>".$getresult."</td>";
break; // to stop looping.
}
}
I want to record downloads in a text file
Someone comes to my site and downloads something, it will add a new row to the text file if it hasn't already or increment the current one.
I have tried
$filename = 'a.txt';
$lines = file($filename);
$linea = array();
foreach ($lines as $line)
{
$linea[] = explode("|",$line);
}
$linea[0][1] ++;
$a = $linea[0][0] . "|" . $linea[0][1];
file_put_contents($filename, $a);
but it always increments it by more than 1
The text file format is
name|download_count
You're doing your incrementing outside of the for loop, and only accessing the [0]th element so nothing is changing anywhere else.
This should probably look something like:
$filename = 'a.txt';
$lines = file($filename);
// $k = key, $v = value
foreach ($lines as $k=>$v) {
$exploded = explode("|", $v);
// Does this match the site name you're trying to increment?
if ($exploded[0] == "some_name_up_to_you") {
$exploded[1]++;
// To make changes to the source array,
// it must be referenced using the key.
// (If you just change $v, the source won't be updated.)
$lines[$k] = implode("|", $exploded);
}
}
// Write.
file_put_contents($filename, $lines);
You should probably be using a database for this, though. Check out PDO and MYSQL and you'll be on your way to awesomeness.
EDIT
To do what you mentioned in your comments, you can set a boolean flag, and trigger it as you walk through the array. This may warrant a break, too, if you're only looking for one thing:
...
$found = false;
foreach ($lines as $k=>$v) {
$exploded = explode("|", $v);
if ($exploded[0] == "some_name_up_to_you") {
$found = true;
$exploded[1]++;
$lines[$k] = implode("|", $exploded);
break; // ???
}
}
if (!$found) {
$lines[] = "THE_NEW_SITE|1";
}
...
one hand you are using a foreach loop, another hand you are write only the first line into your file after storing it in $a... it's making me confuse what do you have in your .txt file...
Try this below code... hope it will solve your problem...
$filename = 'a.txt';
// get file contents and split it...
$data = explode('|',file_get_contents($filename));
// increment the counting number...
$data[1]++;
// join the contents...
$data = implode('|',$data);
file_put_contents($filename, $data);
Instead of creating your own structure inside a text file, why not just use PHP arrays to keep track? You should also apply proper locking to prevent race conditions:
function recordDownload($download, $counter = 'default')
{
// open lock file and acquire exclusive lock
if (false === ($f = fopen("$counter.lock", "c"))) {
return;
}
flock($f, LOCK_EX);
// read counter data
if (file_exists("$counter.stats")) {
$stats = include "$counter.stats";
} else {
$stats = array();
}
if (isset($stats[$download])) {
$stats[$download]++;
} else {
$stats[$download] = 1;
}
// write back counter data
file_put_contents('counter.txt', '<?php return ' . var_export($stats, true) . '?>');
// release exclusive lock
fclose($f);
}
recordDownload('product1'); // will save in default.stats
recordDownload('product2', 'special'); // will save in special.stats
personally i suggest using a json blob as the content of the text file. then you can read the file into php, decode it (json_decode), manipulate the data, then resave it.