how can I sort properly with preg_match? - php

I'm trying to modify a line in PHP file that deals with data that comes from XML(about 600 stations). The php make this data usable by a streamer media player.
The original line is this
if (($title <> "")&& (strpos($link,"<") === false)&& preg_match("/Cha/i",$lang))
this gives me about 50 stations, I want to add few stations that do not have "Cha" in $lang but "Soprts" and has "China" in their $title.
So I wrote the line like this
if (($title <> "")&& (strpos($link,"<") === false)&& preg_match("/Cha/i",$lang)&& (preg_match("/China/i",$title)||preg_match("/Sports/i",$lang)))
But now I'm getting less results than before, now I'm getting only the stations that have CHA in $lang and "China" in $title. All the relevant stations that have CHA in $lang but not "China" in $title are ruled out.
As I have very limited knowledge in PHP I don't know how to make the proper sorting, someone offered me to use stripos but I don't know how to use it and his example didn't worked OK

You flipped the and and or in your new code. You want:
if (($title <> "")&& (strpos($link,"<") === false)&& (preg_match("/Cha/i",$lang)|| (preg_match("/China/i",$title)&&preg_match("/Sports/i",$lang))))

You dont put bracets corretly. You can add multiple options in regex by using | (means OR) ,try this:
if (($title <> "") && (strpos($link,"<") === false) && preg_match("/CHA|China|Sports/i",$lang))

Related

PHP "||" is returning the wrong value

I am making an upload script for a music-related thing i am building.
I check whether the file is an MP3 or an OGG, but even if it IS, php will return true on this and say that it isnt on either of these checks.
Here's some example code:
$ft = "mp3";
if($ft != "mp3" || $ft != "ogg") { echo "not an ogg / mp3"; }
What it returns:
not an ogg / mp3
If i am doing something wrong, i am more than glad to be crapped on by Stack Overflow this time, cuz at least i know i did something stupidly wrong.
|| operator means or so if one of the following conditions is true it will do the action of the condition , you need to change it to && which means the both condition should be true to do the action

PHP system() fail silently when calling a python script that processes file with UTF-8 encoding

Tl;dr: Consider using python framework Bottle instead of PHP. If you can't, I have python2-specific solution link at the bottom of this post.
I made simple markov chain python program. It operates on two wordlists, greek.txt and japanese.txt. Note that japanese.txt contains the Ō character, but the problem persisted even when I replaced the characters with regular O.
I want to make really simple, small and dirty PHP API.
When I call PHP file, it should echo output of command python3 markov-chain.py $_GET['file'] 10 $_GET['min'] $_GET['max'].
I have this:
<?php
if(isset($_GET["file"]) && isset($_GET["min"]) && isset($_GET["max"])) {
if($_GET["file"] != null && $_GET["min"] != null && $_GET["max"] != null && is_numeric($_GET["min"]) && is_numeric($_GET["max"])) {
# Yeah, it should be fine. Just check for $file in whitelist
$filename = $_GET["file"];
$min_len = $_GET["min"];
$max_len = $_GET["max"];
$count = 10;
if( $filename === "japanese.txt" || $filename == "greek.txt" ) {
$command = 'python3 markov-chain.py ' . $filename . ' ' . $count . ' ' . $min_len . ' ' . $max_len;
echo($command);
echo(system($command, $statuscode));
echo('S:'.$statuscode);
echo('E:'.error_get_last());
}
}
}
?>
When I call this on the greek.txt wordlist, everything works as expected. However, when I call it on japanese.txt, status code is 1 and nothing is sent to output of system(). When I copy&paste the generated command into terminal, it works without issues even for the japanese.txt variant.
I tried to make test.sh file that would have hardcoded arguments:
#!/bin/sh
python3 markov-chain.py greek.txt 10 3 6 2>> errorlog.txt
When I call this file from PHP, it works. However when I change the test.sh file to work with japanese.txt wordlist, I still get nothing as an output and 1 as status code. Invoking the test.sh from terminal works perfectly for both variants (greek and japanese). Nothing is written to error log file (the file isn't even created!) when I call the test.sh from PHP.
Greek wordlist
Japanese wordlist
Edit:
Greek wordlist is ASCII, and Japanese wordlist is UTF-8, so PHP doesn't accept (or Python doesn't correctly send) UTF-8 encoding.
Edit:
Not really a solution, but I ended up switching to Python framework Bottle, it's exactly why I used PHP: I just write it in one file and it... works. Great for simple APIs I just need to quickly hack together.
Concerning the issue with UTF-8, I found this, but was not able to solve my problem anyway. Hopefully it helps someone.

How to solve a Undefined offset when reading a csv file with PHP.?

Hello to all so kind persons who are always there to help us.
I need to importa a csv file to mysql using php.
the code I have until now is as follows:
Steps:
make all the corresponding validations.
make a mysql connection.
//process the csv file
$handle = fopen($_FILES['file']['tmp_name'], "r");
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$att0 = mysql_real_escape_string($data[1]);
$att1 = mysql_real_escape_string($data[1]);
$att2 = mysql_real_escape_string($data[2]);
etc, etc.
$sql = "INSERT INTO Alumnos etc, etc.";
mysql_query($sql);
Error:
Notice: Undefined offset: 1 in D:\www\studentAdministrator\imports\importar1.php on line 58
I'll appreciate any help. thanks in advance.
I Solved my problem. I changed the semicolon by comma
I appreciate the answers that have already posted
As I said in my comment, this may be caused by exporting a line that has blank cells at the end. Some utilities will end the line after the last cell, instead of putting in the appropriate number of delimiters. Check your file, and if that's the problem, you can just add a little logic to your script to deal with it -- check isset() for each index before you try to use it, and if it doesn't exist, substitute an empty string (or null, or whatever you use for an empty cell elsewhere in the file).
Check your variables before they are passed and used like this:
if(isset($data[1]))? $att0 = mysql_real_escape_string($data[1]) : $att0='null';
You can set it to whatever you like, just thought you might be able to see the NULL nice and easy that way.
If you know that the CSV file will have columns missing, but always in the right order (probably not a great example in this scenario, but worth mentioning) you can also do something like this:
for($i=0;$i<count($data);$i++)
{
echo 'Value '.$i.' is: '.$data[$i].'\n';
}
This will parse through however many items there are per line and you can use them without worrying about the number. Again, in your scenario, probably not the best, but worth mentioning.

Best way to extract text from a 1.3GB text file using PHP?

I have a 1.3GB text file that I need to extract some information from in PHP. I have researched it and have come up with a few various ways to do what I need to do, but as always am after a little clarification on which method would be best or if another better exists that I do not know about?
The information I need in the text file is only the first 40 characters of each line, and there are around 17million lines in the file. The 40 characters from each line will be inserted into a database.
The methods I have are below;
// REMOVE TIME LIMIT
set_time_limit(0);
// REMOVE MEMORY LIMIT
ini_set('memory_limit', '-1');
// OPEN FILE
$handle = #fopen('C:\Users\Carl\Downloads\test.txt', 'r');
if($handle) {
while(($buffer = fgets($handle)) !== false) {
$insert[] = substr($buffer, 0, 40);
}
if(!feof($handle)) {
// END OF FILE
}
fclose($handle);
}
Above is read each line at a time and get the data, I have all the database inserts sorted, doing 50 inserts at a time ten times over in a transaction.
The next method is the same as above really but calling file() to store all the lines in an array before doing a foreach to get the data? I am not sure about this method though as the array would essentially have over 17 million values.
Another method would be to extract only part of the file, rewrite the file with the unused data, and after that part has been executed recall the script using a header call?
What would be the best way in terms of getting this done in the most quick and efficient manner? Or is there a better way to approach this that I have thought of?
Also I plan to use this script with wamp, but running it in a browser while testing has caused problems with timeout even with setting script time out to 0. Is there a way I can execute the script to run without accessing the page through a browser?
You have it good so far, don't use "file()" function as it would most probably hit RAM usage limit and terminate your script.
I wouldn't even accumulate stuff into "insert[]" array, as that would waste RAM as well. If you can, insert into the database right away.
BTW, there is a nice tool called "cut" that you could use to process the file.
cut -c1-40 file.txt
You could even redirect cut's stdout to some PHP script that inserts into database.
cut -c1-40 file.txt | php -f inserter.php
inserter.php could then read lines from php://stdin and insert into DB.
"cut" is a standard tool available on all Linuxes, if you use Windows you can get it with MinGW shell, or as part of msystools (if you use git) or install native win32 app using gnuWin32.
Why are you doing this in PHP when your RDBMS almost certainly has bulk import functionality built in? MySQL, for example, has LOAD DATA INFILE:
LOAD DATA INFILE 'data.txt'
INTO TABLE `some_table`
FIELDS TERMINATED BY ''
LINES TERMINATED BY '\n';
( #line )
SET `some_column` = LEFT( #line, 40 );
One query.
MySQL also has the mysqlimport utility that wraps this functionality from the command line.
None of the above. The problem with the using fgets() is it does not work as you expect. When the maximum characters is reached, then the next call to fgets() will continue on the same line. You have correctly identified the problem with using file(). The third method is an interesting idea, and you could pull it off with other solutions as well.
That said, your first idea of using fgets() is pretty close, however we need to slightly modify its behaviour. Here's a customized version that will work as you'd expect:
function fgetl($fp, $len) {
$l = 0;
$buffer = '';
while (false !== ($c = fgetc($fp)) && PHP_EOL !== $c) {
if ($l < $len)
$buffer .= $c;
++$l;
}
if (0 === $l && false === $c) {
return false;
}
return $buffer;
}
Execute the insert operation immediately or you will waste memory. Make sure you are using prepared statements to insert this many rows; this will drastically reduce execution time. You don't want to submit the full query on each insert when you can only submit the data.

Dealing with infinite loops

I'm trying to learn PHP programming through trial, error and lots and lots of practice.
I've been working on a directory bases image gallery for the last few days and it seems to work fine. I can upload pictures and create new albums. Plus whenever I see a full size picture I have links to the previous and next pictures in the directory.
Now this is where I ran into problems. Once you got to the end of the directory the code would start an infinite loop while it searches for the next file, which isn't there.
So I altered my code and it now looks something like this:
$x = 1;
$dir = opendir($base.'/'.$get_album);
while ((($file = readdir($dir)) !== FALSE) && ($x == 1)) {
while ($img < $file) {
$img++;
$image_exists = file_exists($base.'/'.$get_album.'/'.$img);
if ($image_exists) {
echo "<a href='member.php?album=$get_album&imgID=$img'>
<img src='$base/$get_album/$img' width='70' align='right'>
</a>";
break;
}
$x++;
}
}
This works when I get to the last picture in the directory. So I thought I'd do the same for when I get to the first picture and just invert the operators like so:
$x = 1;
$dir = opendir($base.'/'.$get_album);
while ((($file = readdir($dir)) !== FALSE) && ($x == 1)) {
while ($img > $file) {
$img--;
$image_exists = file_exists($base.'/'.$get_album.'/'.$img);
if ($image_exists) {
echo "<a href='member.php?album=$get_album&imgID=$img'>
<img src='$base/$get_album/$img' width='70' align='right'>
</a>";
break;
}
$x++;
}
}
This however DOES NOT work. I can't understand why that would be the case and I've tried to change things around a few dozen times but I cant seem to make it stop looping.
What am I doing wrong?
Thanks in advance for your help (and for reading through all this).
The issue could likely be related to the fact that readdir returns a string, and you are treating it as if you know its a number. You might find that it is returning you something at the start or end, such as the parent directory '..' as a string or the current directory as a string '.'.
If you want to iterate over the directories, you should check that the return value from readdir is not '.' or '..' specifically.
Please use a better format to your code (it's really painful read it), for instance, in netbeans you can use shiftalt F to format automatically.
I want address your attention to this line:
$image_exists= file_exists($base.'/'.$get_album.'/'.$img);
That is a possible source of errors. If only $base.'/'.$get_album.'/' exists then:
$image_exists= file_exists($base.'/'.$get_album.'/'.$img); // is true even if $img is empty!!!
But moreover:
What is $img? You treat it as a number when do $img++ and then as a string. That is not good for your health.
A good start it should be initialize your vars at the beginning of your code. And then use them in consonance.
I think there is something fundamentally wrong with the design, you are comparing $img, an uninitialized integer, to $file, a string.
It also seems needlessly complicated, as you are reading files from a directory, then check if they exist and break out of your loop if they do.
Perhaps with a clear view of the directory structure and what you are trying to do, I could provide a more detailed answer, but I think you need to go back to the drawing board.

Categories