Finding an occurence of a string after a certain string - php

I'm trying to detect priority of emails (which are stored as plain text in a variable), each email has a 'comments' section and I'm looking to search for terms like 'urgent' or 'high' within the comments area but nowhere else, as these sort of terms are in other places.
So far, what I've been doing was:
if (stristr($body, 'Comment: urgent')){
$urgent = true;
echo '<b>Urgent.</b>';
}
Obviously this doesn't work for cases where 'urgent' is in a sentence like, 'This is urgent'.
How can I search through $body after the substring "Comment:"?
Thanks!

You can use Regular expression:
<?php
$string = 'rweiuowreuiwuier Comment: higewrwre werwrewre high';
if (preg_match('#Comment: (urgent|high)#i',$string)){
$urgent = true;
echo '<b>Urgent.</b>';
}
However you should consider if someone put inside body Comment: high this mail will be also consider as high

The following function - which could do with a new name, takes three parameters.
$a being the Start Frame
$b being the End Frame
$s being the full string
$a would be 'Comment: '
$b would be whatever is at the end of your comments section
$s would be the email string
return value would be the string inbetween, then run your stripos on the return value.
function getMiddle($a, $b, $s) {
return strstr(substr($s, strpos($s, $a) + strlen($a)), $b, true);
}
Example: #Note, the second parameter would need to be specialized to your email#
if (stripos(getMiddle('Comments: ', 'Sincerely', $email), 'urgent') === false) {
echo "URGENT";
}

You can find a string with the function strpos
$mystring = 'Comment: urgent';
$find_string = 'urgent';
$pos = strpos($mystring, $find_string);
if ($pos !== false) {
echo "I find it!";
} else {
echo "Not found";
}

Related

Searching for occurence of a string in a comma delimited list

I have a comma separated list and in that list i am interested to know if a specific string that starts in a certain way is present.
$accounting = 'acc';
$str = 'loan,k,hi,588888,acc';
if (strpos($str, $accounting) === TRUE)
{
echo 'that contained accounting';
}
else{
echo 'nothing was found';
}
The code is giving me nothing is found.Does strpos work in a comma delimited list?.
Does strpos work in a comma delimited list?.
No, it doesn't, because $str is not a list, it's just a string. You have to convert it to a list (=array) first:
$lst = explode(',', $str);
and then search this list:
if(in_array('acc', $lst)....
Your wording is a bit unclear, but if you're looking for a list element that starts with a specific string, it's more complicated:
function has_element_that_starts_with($lst, $prefix) {
foreach($lst as $item)
if(strpos($item, $prefix) === 0) // note three ='s
return true;
return false;
}
Another option is a regular expression:
if(preg_match("~(^|,){$acc}(,|$)~", $str)....
for partial strings:
if(preg_match("~(^|,){$acc}~", $str)....
Your code is right change === to ==. will work.
$accounting = 'acc';
$str = 'loan,k,hi,588888,acc';
if (strpos($str, $accounting) == TRUE)
{
echo 'that contained accounting';
}
else{
echo 'nothing was found';
}
Use php strstr() , Reference
$accounting = 'acc';
$str = 'loan,k,hi,588888,acc';
if (strstr($str, $accounting) )
{
echo 'that contained accounting';
}
else{
echo 'nothing was found';
}

Replace multiple items between tags in a string

Trying to write a function that will replace #something# and #anything# in any string with items in my db that match the name "something" and "anything".
This should work for no matter how many different #some-name# there are in my string. Below is what I have so far and it's working, although only the last (#anything#) is being replaced with the correct code when I load in my browser.
Please keep in mind that I'm learning, so I may be completely off on how to go about this. If there is a better way, I'm all ears.
HTML (String)
<p>This is "#something#" I wanted to replace with code from my database. Really, I could have "#anything#" between my pound sign tags and it should be replaced with text from my database</p>
OUTPUT I'm Getting
This is "#something#" I want to replace with code from my database. Really, I could have "Any Name" between my pound sign tags and it should be replaced with text from my database
DESIRED OUTPUT
This is "The Code" I want to replace with code from my database. Really, I could have "Any Name" between my pound sign tags and it should be replaced with text from my database
FUNCTION in CMS class a.php
public function get_snippets($string) {
$regex = "/#(.*?)#/";
preg_match_all($regex, $string, $names);
$names = $names[1];
foreach ($names as $name){
$find_record = Snippet::find_snippet_code($name);
$db_name = $find_record->name;
if($name == $db_name) {
$snippet_name = "/#".$name."#/";
$code = $find_record->code;
}
}
echo preg_replace($snippet_name, $code, $string);
}
FUNCTION in Snippet class b.php
public static function find_snippet_code($name) {
global $database;
$result_array = static::find_by_sql("SELECT * from ".static::$table_name." WHERE name = '{$name}'");
return !empty($result_array) ? array_shift($result_array) : false;
}
It's because your preg_replace occurs outside of the foreach() loop, so it only happens once.
Here is a working example based on your code which returns $string.
Note that I also use PREG_SET_ORDER which gives me each match as its own array:
function get_snippets($string) {
$regex = '/#([^#]+)#/';
$num_matches = preg_match_all($regex, $string, $matches, PREG_SET_ORDER);
if ($num_matches > 0) {
foreach ($matches as $match) {
// Each match is an array consisting of the token we matched and the 'name' without the special characters
list($token, $name) = $match;
// See if there is a matching record for 'name'
$find_record = Snippet::find_snippet_code($name);
// This step might be redundant, but compare name with the record name
if ($find_record->name == $name) {
// Replace all instances of #token# with the code from the matched record
$string = preg_replace('/'.$token.'/', $find_record->code, $string);
}
}
}
return $string;
}
What you're looking for is preg_replace_callback():
public function get_snippets($string)
{
$regex = "/#(.*?)#/";
return preg_replace_callback($regex, function($match) {
$find_record = Snippet::find_snippet_code($match[1]);
return $find_record === false ? '' : $find_record->code;
}, $string);
}

What is the correct return type of strpos? Searching for the '#' char

For example I have a string I am # the penthouse.
I need to know how to find the character "#" in php string and the position of the character.
I tried strpos but its not working.
Thanks for the help in advance.
EDIT:
I've been using this for get the character:
$text = "I am # the penthouse";
$pos = strrpos($text, '#');
if($pos == true)
{
echo "yes";
}
I would do this
Note, I'm using strpos, not reverse counterpart, strrpos
if (($pos = strpos('I am # the penthouse.', '#') !== false) {
echo "pos found: {$pos}";
}
else {
echo "no # found";
}
Note: Because # could be the first character in a string, strpos could return a 0. Consider the following:
// check twitter name for #
if (strpos('#twitter', '#')) { ... }
// resolves to
if (0) {
// this will never run!
}
So, strpos will explicitly return false when no match is found. This is how to properly check for a substring position:
// check twitter name for #
if (strpos('#twitter', '#') !== false) {
// valid twitter name
}
You can also use the function strpos() for that purpose. Like strrpos() it searches for a substring - or at least a char - in a string but it the returns the first position of that substring or boolean(false) if the substring was not found. So the snippet would look like:
$position = strpos('I am # the penthouse', '#');
if($position === FALSE) {
echo 'The # was not found';
} else {
echo 'The # was found at position ' . $position;
}
Note that there are common pitfalls that come with strpos() and strrpos() in php.
1 . Check Type of the return value!
Imagine the following example :
if(!strpos('#stackoverflow', '#')) {
echo 'the string contains no #';
}
The would output that '#' was not found although the string contains an '#'. Thats because of the weak data typing in PHP. The previous strpos() call will return int(0) because it is the first char in string. But unless you enforce a strict type check using the '===' operator this int(0) will be handle as FALSE. This is the correct way:
if(strpos('#stackoverflow', '#') === FALSE) {
echo 'the string contains no #';
}
2 . Use the correct order of arguments!
The signature of strpos is:
strpos($haystack, $needle [, $start]);
Thats unlike other str* functions in PHP where the $needle is the first arg.
Keep this in mind! ;)
This seems to be working for me in PHP 5.4.7:
$pos = strpos('I am # the penthouse', '#');
What do you mean exactly by strpos is not working?
Look this is working for me, it will also work for you
$string = "hello i am # your home";
echo strpos($string,"#");
i hope this will help -
<?php
$string = "I am # the penthouse";
$desired_char = "#";
// checking whether # present or not
if(strstr($string, $desired_char)){
// the position of the character
$position = strpos('I am # the penthouse', $desired_char);
echo $position;
}
else echo $desired_char." Not found!";
?>

Convert lib_string to string w/o Regex

I need to convert lib_someString to someString inside a block of text using str_replace [not regex].
Here's an example to give an exact sense what I mean: lib_12345 => 12345. I need to do this for a bunch of instances in a block of text.
Below is my attempt. Problem I'm getting is that my function is not doing anything (I just get lib_id returned).
function extractLibId($val){ // function to get the "12345" in the above example
$lclRetVal = substr($val, 5, strlen($val));
return $lclRetVal;
}
function Lib($text){ // does the replace for all lib_ instances in the text
$lclVar = "lib_";
$text = str_replace($lclVar, "<a href='".extractLibId($lclVar)."'>".extractLibId($lclVar)."</a>", $text);
return $text;
}
Regexp gonna be faster and more clear, you will have no need to call your function for every possible 'lib_' string:
function Lib($text) {
$count = null;
return preg_replace('/lib_([0-9]+)/', '$1', $text, -1, $count);
}
$text = 'some text lib_123123 goes here lib_111';
$text = Lib($text);
Without regexp, but every time Lib2 will be called somewhere will die cute kitten:
function extractLibId($val) {
$lclRetVal = substr($val, 4);
return $lclRetVal;
}
function Lib2($text) {
$count = null;
while (($pos = strpos($text, 'lib_')) !== false) {
$end = $pos;
while (!in_array($text[$end], array(' ', ',', '.')) && $end < strlen($text))
$end++;
$sub = substr($text, $pos, $end - $pos);
$text = str_replace($sub, ''.extractLibId($sub).'', $text);
}
return $text;
}
$text = 'some text lib_123123 goes here lib_111';
$text = Lib2($text);
Use preg_replace.
Although it is possible to do what you need without regular expressions, you say you don't want to use them because of performance reasons. I doubt the other solution will be faster, so here is a simple regex to benchmark against:
echo preg_replace("/lib_(\w+)/", '$1', $str);
As shown here: http://codepad.org/xGj78r9r
Ignoring how ridiculous area of optimizing this is, even the simplest implementation with minimal validation already takes only 33% less time than a regex
<?php
function uselessFunction( $val ) {
if( strpos( $val, "lib_" ) !== 0 ) {
return $val;
}
$str = substr( $val, 4 );
return "{$str}";
}
$l = 100000;
$now = microtime(TRUE);
while( $l-- ) {
preg_replace( '/^lib_(.*)$/', "$1", 'lib_someString' );
}
echo (microtime(TRUE)-$now)."\n";
//0.191093
$l = 100000;
$now = microtime(TRUE);
while( $l-- ) {
uselessFunction( "lib_someString" );
}
echo (microtime(TRUE)-$now);
//0.127598
?>
If you're restricted from using a regex, you're going to have difficult time searching for a string you describe as "someString", i.e. not precisely known in advance. If you know the string is exactly lib_12345, for example, then set $lclVar to that string. On the other hand, if you don't know the exact string in advance, you'll have to use a regex via preg_replace() or a similar function.

PHP stristr issue

$bodytext = "we should see this text <more> but not this at all <html>";
if(stristr($bodytext, "<more>") == TRUE)
{
$find = "<more>";
$pos = stripos($bodytext, $find);
$bodytext = substr($bodytext, 0, $pos);
}
echo "$bodytext";
If the $bodytext contains other html code, this also causes the above code to return true :
<more
more>
How do I adjust my code so only (and exactly) :
<more>
returns true?
Simple/naiive:
$bodytext = preg_replace('/(.*?)<more>.*/', $1, $bodytext);
stristr returns all of the string from the match to the end of the string. If a match is not found, it returns false.
You therefore need to do this:
if(stristr($bodytext, "<more>") !== false) {
// match found
}
stripos is more suited to your needs:
$pos = stripos($bodytext, "<more>");
if($pos !== false) {
// match found
}
Alternative: See Marc B's answer, which does everything you appear to be trying to achieve in a single statement.
You could also use the explode function and output the first element of the array
$bodytext = "we should see this text <more> but not this at all <html>";
if(stristr($bodytext, "<more>") == TRUE)
{
$split = explode('<more>', $bodytext);
echo $split[0];
}

Categories