So I know how to open a file in php is done using
fopen("file.txt", 'r') ;
but i want to get one line in the file and so some string manipulation on it.
such as " Serving this with <0101010> "
I want to find the line that starts with "Serving this" and take the whole line add it to $line
Then i will get remove the <> and add it to $number , and same for <0101010>
names of methods that can be used would be just perfect
Okay, the simple method you probably want to use is:
foreach (file("file.txt") as $line) {
if (strpos($line, "Serving this with") === 0) {
print "found";
The file function is easier than fopen/fread, as it returns a list of lines already. And the strpos function simply searches the string and returns the position. It must be checked with === 0 here, because it could also return false.
Instead of printing "found" you want to extract something, so you must again use strpos to find your delimeters < and > and then extract the part with substr:
$l = strpos($line, "<"); // well, actually needs more logic,
$r = strpos($line, ">"); // some if tests, if both are true
$wanthave = substr($line, $l, $r - $l + 1);
A simpler option I would use are regular expressions. And the regex itself looks simple enough in your case:
preg_match_all('/^Serving this with <(\d+)>/m',
file_get_contens("file.txt"),
$matches);
print_r($matches[1]);
you can also use fgets() read file line by line.
$line = fgets($file_handle);
Related
Hello i'm trying to find a the rest of the string knowing only the beginning of it.
Example:
I have start of string Dude=99999
Number 99999 changes its not always the same but word Dude is always the same.
So my question is how can i find the rest of the string after word Dude...
I know in linux there is something like t*.txt but in php? help please.
SHORT: find 'dude= and read the string until '
This sounds like a good match for a regex:
$regex = "/\'Dude=([0-9]+)\'/";
$str = "'Duck=123456' 'Chicken=982731' 'Dude=123487' 'Boat=129832'";
preg_match_all($regex, $str, $matches, PREG_SET_ORDER, 0);
echo $matches[0][1]; // prints: 123487
If your input string/text has line-breaks, you will probably need additional flags for the regex matcher. But there are already questions and answers for this available, so please refer to the search.
You should use "str_replace()" function for this
echo str_replace("dude=","","dude=99999");
Here first parameter your fix string which would be start as above , second parameter is replacement string, which is put as empty , third parameter is your actual string
If you're going to check all lines for different strings you can do as I have done recently:
// loop through all uploaded files:
for ($key = 0; $key < count($_FILES['file']['tmp_name']); $key++) {
// make an array of lines from a single file:
$txt_file = file($_FILES['file']['tmp_name'][$key]);
// loop through this array, line by line:
foreach ($txt_file as $line) {
// if your file is not utf-8 fix the encoding:
$line = iconv("windows-1251", "utf-8", $line);
// check if this string begins with 'Dude=':
if (substr($line, 0, strlen('Dude=')) === 'Dude=') {
// if yes, then trim the 'Dude=' and get what's after it:
$found_value[$key]['dude'] = trim(substr($line, strlen('Dude=')));
// if this string begins with 'Dude=' it cannot begin with something else,
// so we can go straight to the next cycle of the foreach loop:
continue;
// check if this string begins with 'Something else=':
} elseif (substr($line, 0, strlen('SomethingElse=')) === 'SomethingElse=') {
// if yes, then trim the 'SomethingElse=' and get what's after if:
$found_value[$key]['something_else'] = trim(substr($line, strlen('SomethingElse=')));
// if there's more items to find in the string use 'continue' to shorten server's work
continue;
}
}
}
I've adapted and commented it for you. Also you probably want to check if file(s) was uploaded properly, so you can use file_exists and is_uploaded_file
In the end you will get an array with structure like this:
$found_value [
1 => array()[
'dude' => 9999999
'something_else' => 'hello'
]
2 => array()[
'dude' => 3765234
'something_else' => 'hello again'
]
]
I have a PHP script that loops through each row of a CSV file and organizes each line into an array:
$counter = 0;
$file = file($ReturnFile);
foreach($file as $k){
if(preg_match('/"/', $k)==1){
$csv[] = explode(',', $k);
$counter++;
}
}
...
while($x<$counter){
$line=$csv[$x];
This works; my question is about how to find a substring within each line. This:
foreach($line as $value){
if($value==$name_search){
// action
works if the value of $line is exactly equal to the value of $name_search ($name_search is a person's last name). However, this doesn't work if there is a space or additional characters in the value of $line (for example: $line equal to "Wilson (ID: 345)" or "Wilson " won't match a $name_search value of "Wilson".
So far I've tried:
if(strpos($value, $res_name_search) !== false){
if(substr($value, 0, strrpos($value, ' '))==$res_name_search){
if(substr(strval($value), 0, strrpos(strval($value), ' '))==$res_name_search){
without success ... Do I have a syntax error and/or is there a better way to accomplish this?
I think you have inverted the parameters. The following should work:
if (strpos($res_name_search, $value) !== false)
A minor note: use stripos for case-insensitive search.
Try to use strpos like this: if (strpos($res_name_search, $value))
use php TRIM function
Convert to either of the lowercase or uppercase before compairing
use var_dump to check the data type
instead of using var_dump type cast $value and $name_search to STRING
also check ===
Remove spaces (if required)
Use regular expression to remove (, ), :, -, ; etc...
and of course apply function strpos
You can apply above mentioned points in your logic (Order of points may be different)
Try this:
$str = 'This is my test: wilson ';
$search = "wilson";
if(strpos(strtolower($str), strtolower($search)) !== false){
echo 'found it';
}
You can also try this:
if (preg_match('/'.strtolower($res_name_search).'/', strtolower($value)))
This is the sort of situations for which the built-in PHP function stristr exists. This function is the case-insensitive equivalent of the strstr function which, according to the docs:
Returns part of haystack string starting from and including the first occurrence of needle to the end of haystack.
Using this function, achieving such a task becomes as easy as:
foreach($line as $value){
if( stristr($value, $name_search) !== FALSE){
// substring was found in search string, perform your action
You can read more about it in the official documentation
I hope this helps.
I advice you to use fgetcsv function, this will return you an array of your columns for each iteration as follow :
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// ...
}
If in your CSV file, the column NAME is in position 2 for example and you want to know if token exist, just use
if (strpos('Wilson', $data[2] !== FALSE) {
// do your job
}
if you want to deal with case-insentivie, use stripos function
I need to compare two language files - English and German. Each text file has one word/phrase per line. Word/phrase [x] in first language is word/phrase [x] in second language. The translated word is on the same line in the second file.
I tried to get the translation using the following code, but it seems that the loop does not work. I always get "none". Any ideas?
function translation($word,$service,$sprache1,$sprache2){
$typus ="transl";
$mypath = "data/".$service."/";
mkdir($mypath,0777,TRUE);
//fh - First language file
$myFile = $mypath."".$typus."-".$sprache1.".txt";
$fh = file($myFile) or die("can't open file");
//fh2 - Second language file
$myFile2 = $mypath."".$typus."-".$sprache2.".txt";
$fh2 = file($myFile2) or die("can't open file");
$x=0;
$result = "none";
foreach ($fh as $line) {
if (stripos($word,$line))
{$result = $fh2[$x];
break;
}
$x=$x+1;
}
return $result;
}
I think your problem is in wrong if statement.
The point is that stripos (like strpos) can return 0 or false as a result.
For example if you search for 'cat' in a word 'cats' stripos will return 0, as it's the first position of cat-string.
On the other side, if you search 'dog' in a word 'cats' stripos will return false as nothing is found.
So in you function the if case should be more strict:
if (stripos($word,$line) !== false)
This means that your word is found even if it starts from position 0.
You current if statement doesn't allow 0 (zero) value to be accepted.
After testing your code I found 2 different problems.
First of all, be careful with stripos. This function returns 0 if the $needle is found at the beginning (i.e. position 0), and false if the $needle was not found. In PHP, 0 is eval'd to false by default.
You should change your if statement to:
if(stripos($word, $line) !== false)
Note the !== operator, which is stronger than !=.
The second and most important problem, which prevents your function from working, is that you compare lines which can contains invisible characters (e.g. "newline" chars). You should trim the strings before comparing them.
I'd change your if statement for:
if(trim($word) === trim($line))
which is simpler. Or if you really want to keep stripos:
if(stripos(trim($word), trim($line)) !== false)
Question 1: How can I manually move the fgetc file pointer from its current location to the next line?
I'm reading in data character by character until a specified number of delimiters are counted. Once the delimiter count reaches a certain number, it needs to copy the remainder of the line until a new line (the record delimiter). Then I need to start copying character by character again starting at the next record.
Question 2: Is manually moving the file pointer to the next line the right idea? I would just explode(at "\n") but I have to count the pipe delimiters first because "\n" isn't always the record delimiter.
Here's my code (it puts all the data into the correct record until it reaches the last delimiter '|' in the record. It then puts the rest of the line into the next record because I haven't figured out how to make it correctly look for the '\n' after specified # of | are counted):
$file=fopen("source_data.txt","r") or exit ("File Open Error");
$record_incrementor = 0;
$pipe_counter = 0;
while (!feof($file))
{
$char_buffer = fgetc($file);
$str_buffer[] = $char_buffer;
if($char_buffer == '|')
{
$pipe_counter++;
}
if($pipe_counter == 46) //Maybe Change to 46
{
$database[$record_incrementor] = $str_buffer;
$record_incrementor++;
$str_buffer = NULL;
$pipe_counter = 0;
}
}
Sample Data:
1378|2009-12-13 11:51:45.783000000|"Pro" |"B13F28"||""|1||""|""|""|||False|||""|""|""|""||""||||||2010-12-15 11:51:51.330000000|108||||||""||||||False|""|""|False|""|||False
1379|2009-12-13 12:23:23.327000000|"TLUG"|"TUG"||""|1||""|""|""|||False|||""|""|""|""||""||||||1943-04-19 00:00:00|||||||""||||||False|""|""|False|""|||False
I'd say that doing this via file handling functions is a bit clumsy, when it could be done via regular expression quite easily. Just read the entire file into a string using file_get_contents() and doing a regular expression like /^(([^|]*\|){47}([^\r\n]*))/m with preg_match_all() could find you all the rows (which you can then explode() using | as the delimiter and setting 48 as the limit for number of fields.
Here is a working example function. The function takes the file name, field delimiter and the number of fields per row as the arguments. The function returns 2 dimensional array where first index is the data row number and the second is the field number.
function loadPipeData ($file, $delim = '|', $fieldCount = 48)
{
$contents = file_get_contents($file);
$d = preg_quote($delim, '/');
preg_match_all("/^(([^$d]*$d){" . ($fieldCount - 1) . '}([^\r\n]*))/m', $contents, $match);
$return = array();
foreach ($match[0] as $line)
{
$return[] = explode($delim, $line, $fieldCount);
}
return $return;
}
var_dump(loadPipeData('source_data.txt'));
(Note: this is a solution to the original problem)
You can read to the end of the line like this:
while (!feof($file) && fgetc($file) !== '\n');
As for whether or not fgetc is the right way to do this... your format makes it difficult to use anything else. You can't split on \n, because there may be newlines within a field, and you can't split on |, because the end of the record doesn't have a pipe.
The only other option I can think is to use preg_match_all:
$buffer = file_get_contents('test.txt');
preg_match_all('/((?:[^|]*\|){45}[^\n]*\n)/', $buffer, $matches);
foreach ($matches[0] as $row) {
$fields = explode('|', $row);
}
Answer to the modified question:
To read from the file pointer to the end of the line, you can simply use the file reading function fgets(). It returns everything from the current file pointer position until it reaches the end of the line (and also returns the end of the line character(s)). After the function call, the file reading pointer has been moved to the beginning of the next line.
I am trying to remove the word "John" a certain number of times from a string. I read on the php manual that str_replace excepts a 4th parameter called "count". So I figured that can be used to specify how many instances of the search should be removed. But that doesn't seem to be the case since the following:
$string = 'Hello John, how are you John. John are you happy with your life John?';
$numberOfInstances = 2;
echo str_replace('John', 'dude', $string, $numberOfInstances);
replaces all instances of the word "John" with "dude" instead of doing it just twice and leaving the other two Johns alone.
For my purposes it doesn't matter which order the replacement happens in, for example the first 2 instances can be replaced, or the last two or a combination, the order of the replacement doesn't matter.
So is there a way to use str_replace() in this way or is there another built in (non-regex) function that can achieve what I'm looking for?
As Artelius explains, the last parameter to str_replace() is set by the function. There's no parameter that allows you to limit the number of replacements.
Only preg_replace() features such a parameter:
echo preg_replace('/John/', 'dude', $string, $numberOfInstances);
That is as simple as it gets, and I suggest using it because its performance hit is way too tiny compared to the tedium of the following non-regex solution:
$len = strlen('John');
while ($numberOfInstances-- > 0 && ($pos = strpos($string, 'John')) !== false)
$string = substr_replace($string, 'dude', $pos, $len);
echo $string;
You can choose either solution though, both work as you intend.
You've misunderstood the wording of the manual.
If passed, this will be set to the number of replacements performed.
The parameter is passed by reference and its value is changed by the function to indicate how many times the string was found and replaced. Its initial value is discarded.
There are a few things you could do to achieve this, but I can't think of one specific php function that will easily let you do this.
One option is to create your own replace function and utilize strripos and substr to do the replaces.
Another thing you can do is use preg_replace_callback and count the number of replacements you have done in the callback.
There's probably more ways but that's all I can think of on the fly. If performance is an issue I suggest you give both a try and do some simple benchmarks.
The cleanest, most-direct, single function call is to use preg_replace(). Its replacement limiting parameter makes the task intuitive and readable.
$string = preg_replace('/John/', 'dude', $string, $numberOfInstances);
The function is also attractive because making the search case-insensitive is as simple as adding the i pattern modifier to the end of the pattern. I won't delve into the usefulness of word boundaries (\b).
If a search string might contain characters with special meaning to the regex engine, then preg_quote() will be necessary -- this diminishes the beauty of the technique but not prohibitively so.
$search = '$5.99';
$pattern = '/' . preg_quote($search, '/') . '/';
$string = preg_replace($pattern, 'free', $string, $numberOfInstances);
For anyone who has an unnatural bias against regex functions, this can be done without regex and without looping -- it will be case-sensitive though.
Limited Explode & Implode: (Demo)
$numberOfInstances = 2;
$string = 'Hello John, how are you John. John are you happy with your life John?';
// explode here -^^^^ and ---------^^^^ only to create the following array:
// 0 => 'Hello ',
// 1 => ', how are you ',
// 2 => '. John are you happy with your life John?'
echo implode('dude', explode('John', $string, $numberOfInstances + 1));
Output:
Hello dude, how are you dude. John are you happy with your life John?
Notice the explode's limiting parameter dictates how many elements are generated, not how many explosions are executed on the string.
function str_replace_occurrences($find, $replace, $string, $count = -1) {
// current occrurence
$current = 0;
// while any occurrence
while (($pos = strpos($string, $find)) != false) {
// update length of str (size of string is changing)
$len = strlen($find);
// found next one
$current++;
// check if we've reached our target
// -1 is used to replace all occurrence
if($current <= $count || $count == -1) {
// do replacement
$string = substr_replace($string, $replace, $pos, $len);
} else {
// we've reached our
break;
}
}
return $string;
}
Artelius has already described how the function works, ill just show you how to do this via the manual methods:
function str_replace_occurrences($find,$replace,$string,$count = 0)
{
if($count == 0)
{
return str_replace($find,$replace,$string);
}
$pos = 0;
$len = strlen($find);
while($pos < $count && false !== ($pos = strpos($string,$find,$pos)))
{
$string = substr_replace($string,$replace,$pos,$len);
}
return $string;
}
This is untested but should work.