Reputation: 893
Basically i have something like this
Hand #1
First row always has the same info,
if the text matches what im looking for ill find
the keyword in the first line. Bunch of text,
bunch more text bla bla bla
Hand #2
And this is my code that prints out all the text between Hand #1 and Hand#2
$searchfor = 'myKeyword';
$file = file_get_contents($filename);
// find the location of the keyword, this keyword indicates that i want to grab this group
// of text, since each group of text starts off with Hand #x and ends immediately before the next Hand #x i search for the keyword to identify this is a valid group of text
$pos_keyword = strpos($file, $searchfor);
// there might be a more elegant way but the Hand # value i need will always be within 60-70 characters before the keyword
$rollback = $pos_keyword-100;
// this is the start position of the text i want to grab
$start = strpos($file, "Hand #", $rollback);
// we search from the after the keyword and assign to $end
$end = strpos($file, "Hand #", $pos_keyword);
// print out the string between the start and end Hand# keywords
echo "string: " . substr($file,$start,($end-$start)) . "<br />";
echo "<br /><br /><br />";
Now the document has hundreds of those values and i want to repeat that search until the end of the document. I tried googling but people mentioned using !eof($file) can cause loops and i couldnt get it to work, any ideas of what function or loop i would use to loop through this code over and over until the end of the document.
Im guessing i loop, and at the end set the $end as the new $pos_keyword but im not sure what kind of loop is the best one to use, any ideas?
Upvotes: 0
Views: 97
Reputation: 138
First, let me try to restate your question as I understand it:
You have a file which has the following format:
Hand #1
Some text with keywords like apple
Some more text
...
Last line of Block
Hand #2
Oranges are good too
This one only has 2 lines
Hand #3
And so forth.
You want code which will loop through all the lines of the input text and output the complete block of code for keyword matches.
$keywords = array('apple', 'orange');
$handle = @fopen($filename, "r");
if ($handle) {
$block = ""; //redundant, really
//read through the file. When we hit 'Hand #', start filling up $block
while (($line = fgets($handle, 4096)) !== false) {
if(strpos($buffer, 'Hand #') === 0){
foreach($keywords as $keyword){
if(stripos($block, $keyword) !== false){
print "string: {$block}<br />";
break; //only need to match one keyword to print the block
}
}
print "<br /><br /><br />";
$block = ""; //this is the beginning of a block;
}
$block .= $line;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
//check the final block
foreach($keywords as $keyword){
if(stripos($block, $keyword) !== false){
print "string: {$block}<br />";
break; //only need to match one keyword to print the block
}
}
fclose($handle);
}
In a nutshell:
Resources:
Upvotes: 0
Reputation: 173662
Searching for a keyword and then backtracking may not be what you're after, so this would be my recommendation; split up the sections first and then filter them based on whether or not they contain your keyword:
$text = <<<EOS
Hand #1
First row always has the same info,
if the text matches what im looking for ill find
the keyword in the first line. Bunch of text,
bunch more text bla bla bla
Hand #2
Lala alala
EOS;
$keyword = 'keyword';
$block_re = '/(^Hand #)(\d+)(.*?)(?=\1|\Z)/ms';
if (preg_match_all($block_re, $text, $matches, PREG_SET_ORDER)) {
print_r(array_filter($matches, function($match) use ($keyword) {
return strpos($match[3], $keyword);
}));
}
This returns the first segment only; the second one does't contain "keyword".
Upvotes: 2
Reputation: 24435
It's not very often I'd say this, but regex might be a viable option here... Consider the following regex:
/Hand #1(.*?)Hand #2/s
/s
modifier allows .
to match new lines
So you do this:
$file = file_get_contents($filename);
$matches = array();
preg_match('/Hand #1(.*?)Hand #2/s', $file, $matches);
print_r($matches);
Now $matches
contains two keys (if it finds what you want) - the 0
index has the whole string, the 1
index has the matched text. See this example here.
To tidy up and return your matched text, do this:
unset($matches[0]);
$return_text = trim($matches[1]);
Looping
Now, I presume that Hand #1 -> Hand #2
are different for each of your blocks in your file. If that's the case, and you know what they are before you loop, you could do something like this:
$delimiters = array('Hand', 'Dog', 'Cat', 'Person', 'Etc');
$returns = array();
foreach($delimiters as $d) {
$matches = array();
preg_match('/' . $d . ' #1(.*?)' . $d . ' #2/s', $file, $matches);
if(!empty($matches[1]))
$returns[] = trim($matches[1]); // add to output array
}
At the end of this, your $returns
array will contain all matched blocks between all of those delimiters.
If your delimiters are all Hand #1
and Hand #2
, you need to use preg_match_all
, which will return an array containing all matched blocks and you won't need a loop (and the zero index which you'll unset).
Documentation
Examples
Upvotes: 0