Check if all the substring are included in a string using PHP - php

let's say I have 2 set of string to check.
$string = 12345;
$string2 = 15000;
//string must contain 1,2,3,4,5 to be returned true
if(preg_match('[1-5]',$string) {
return true;
} else {
return false;}
This code works for $string but not for $string2. It returns true too with $string2.
Please help!

If string must contain 1, 2, 3, 4 and 5, then you should use regex pattern
/^(?=.*1)(?=.*2)(?=.*3)(?=.*4)(?=.*5).*/
which can be further optimize... for example:
/^(?=.*1)(?=.*2)(?=.*3)(?=.*4).*5/
If no other characters are allowed, then you should use regex pattern
/^(?=.*1)(?=.*2)(?=.*3)(?=.*4)(?=.*5)[1-5]*$/

You can check this with strpos as well:
<?php
function str_contains_all($string, $searchValues, $caseSensitive = false) {
if (!is_array($searchValues)) {
$searchValues = (string)$searchValues;
$searchValuesNew = array();
for ($i = 0; $i < strlen($searchValues); $i++) {
$searchValuesNew[] = $searchValues[$i];
}
$searchValues = $searchValuesNew;
}
$searchFunction = ($caseSensitive ? 'strpos' : 'stripos');
foreach ($searchValues as $searchValue) {
if ($searchFunction($string, (string)$searchValue) === false) {
return false;
}
}
return true;
}
?>
Use:
<?php
$string = 12345;
$string2 = 15000;
if (str_contains_all($string, 12345)) {
echo 'Y';
if (str_contains_all($string2, 12345)) {
echo 'Y';
} else {
echo 'N';
}
} else {
echo 'N';
}
?>
Which outputs:
YN
DEMO

Related

in_array returns false on same characters, single character string matching

function make_ascii($str) {
$special = array('ľ','š','č','ť','ž','ý','á','í','é','ú','ä','ô','ň','ě');
$ascii = array('l','s','c','t','z','y','a','i','e','u','a','o','n','e');
$str = str_split($str);
foreach ($str as $k => $c) {
if(ctype_upper($c)) {
$u = true;
$c = strtolower($c);
} else {
$u = false;
}
if(in_array($c, $special, false)) {
$c = $ascii[array_search($c, $special)];
}
if($u) {
$c = strtoupper($c);
}
$str[$k] = $c;
}
return join($str);
}
In this function, even if I feed characters from $special array the in_array() returns false every time, if I would var_dump() on regular text I try to parse, the output will be just bool(false) with no mach, even if I copy paste the character from source to array. Also I'm looking for way to make this character replacement work.
As str_splitwill not work for multibyte you have to use mb_to perform multibyte string operation
function make_ascii($str) {
//return $str;
$special = array('ľ','š','č','ť','ž','ý','á','í','é','ú','ä','ô','ň','ě');
$ascii = array('l','s','c','t','z','y','a','i','e','u','a','o','n','e');
$str = array_map(function ($i) use ($str) {
return mb_substr($str, $i, 1);
}, range(0, mb_strlen($str) -1));
foreach ($str as $k => $c) {
if(ctype_upper($c)) {
$u = true;
$c = strtolower($c);
} else {
$u = false;
}
// print_r($c);
if(in_array($c, $special)) {
$c = $ascii[array_search($c, $special)];
}
if($u) {
$c = strtoupper($c);
}
$str[$k] = $c;
}
return join($str);
}
var_dump(make_ascii('áé'));
DEMO
If issue with uppercase letters you have to change functions to mb_strtoupper and mb_strtolower. Also ctype_upper will not work so change it also
function make_ascii($str) {
//return $str;
$special = array('ľ','š','č','ť','ž','ý','á','í','é','ú','ä','ô','ň','ě');
$ascii = array('l','s','c','t','z','y','a','i','e','u','a','o','n','e');
$str = array_map(function ($i) use ($str) {
return mb_substr($str, $i, 1);
}, range(0, mb_strlen($str) -1));
foreach ($str as $k => $c) {
if( mb_strtoupper($c, "UTF-8") == $c) {
$u = true;
$c = mb_strtolower($c);
} else {
$u = false;
}
// print_r($c);
if(in_array($c, $special)) {
$c = $ascii[array_search($c, $special)];
}
if($u) {
$c = mb_strtoupper($c);
}
$str[$k] = $c;
}
return join($str);
}
$str = "ľÁľa ýellow";
var_dump(make_ascii($str));
DEMO
As I mentioned str_split can't handle multi-byte strings. Don't believe me? Have a look.
At any rate here's a version that can split multibyte strings:
function make_ascii($str) {
$special = array('ľ','š','č','ť','ž','ý','á','í','é','ú','ä','ô','ň','ě');
$ascii = array('l','s','c','t','z','y','a','i','e','u','a','o','n','e');
$str = preg_split("//u",$str);
foreach ($str as $k => $c) {
if(ctype_upper($c)) {
$u = true;
$c = mb_strtolower($c);
} else {
$u = false;
}
if(in_array($c, $special, false)) {
$c = $ascii[array_search($c, $special)];
}
if($u) {
$c = mb_strtoupper($c);
}
$str[$k] = $c;
}
return join($str);
}
$str = "ľaľa ýellow";
print_r(make_ascii($str));
Prints:
lala yellow

Find a string has two overlapped string PHP

I have two strings abc and bca. I want to check whether an other string contains these both the strings and are not overlapped too. For example:
a string abca contains both but is overlapped.
a string abcxbca contains both and not overlapped.
a string abcxbcabc contains both but is overlapped.
Enjoy :)
<?php
$y1="abc"; //search string1
$y2="bca"; //search string2
$x1="abca"; //contains both but is overlapped.
$x2= "abcxbca"; //contains both and not overlapped.
$x3 ="abcxbcabc"; //contains both but is overlapped.
class Points{
public $start;
public $stop;
public $overlaped=false;
private function Points( $s1, $s2 ) {
$this->start=$s1;
$this->stop=$s2;
$this->overlaped=false;
}
public static function create($s1, $s2){
if (is_numeric($s1)&&is_numeric($s2)){
return new Points($s1, $s2);
}
else return NULL;
}
}
function display($arr){
$cnt1=0;
$cnt2=0;
for ($i=0;$i<count($arr);$i++){
if ($arr[$i]->overlaped===true) $cnt1++;
else $cnt2++;
}
return " ".$cnt2." not overlaped and ".$cnt1." overlaped";
}
function strpos_all($haystack, $needle) {
$offset = 0;
$allpos = array();
while (($pos = strpos($haystack, $needle, $offset)) !== FALSE) {
$offset = $pos + 1;
$allpos[] = Points::create($pos,$pos+strlen($needle));
}
return $allpos; }
function check($haystack,$needle1,$needle2){
$find1= strpos_all($haystack, $needle1);
$find2= strpos_all($haystack, $needle2);
for ($i=0;$i<count($find1);$i++){
for($j =0; $j<count($find2);$j++){
if (max($find1[$i]->start,$find2[$j]->start) <= min($find1[$i]->stop,$find2[$j]->stop)) {
$find1[$i]->overlaped=true;
$find2[$j]->overlaped=true;
}
}
}
echo $needle1.display($find1)."<br>";
echo $needle2.display($find2)."<br>";
}
echo "<br>------Start-------<br>";
echo "String :".$x1."<br>";
check ($x1,$y1,$y2);
echo "<br>-----End----------<br>";
echo "<br>------Start-------<br>";
echo "String :".$x2."<br>";
check ($x2,$y1,$y2);
echo "<br>-----End--------<br>";
echo "<br>------Start-------<br>";
echo "String :".$x3."<br>";
check ($x3,$y1,$y2);
echo "<br>-----End--------<br>";
?>

Is string a math expression?

How can I found if string is a math expression or not?
It is enough to understand basic math expressions +, -, x, /
For Example:
"1+1" => TRUE
"2 / 2" => TRUE
"hello" => FALSE
"1 * 2 - X" => FALSE
"me + u" => FALSE
class MathExpression {
private static $parentheses_open = array('(', '{', '[');
private static $parentheses_close = array(')', '}', ']');
protected static function getParenthesesType( $c ) {
if(in_array($c,MathExpression::$parentheses_open)) {
return array_search($c, MathExpression::$parentheses_open);
} elseif(in_array($c,MathExpression::$parentheses_close)) {
return array_search($c, MathExpression::$parentheses_close);
} else {
return false;
}
}
public static function validate( $expression ) {
$size = strlen( $expression );
$tmp = array();
for ($i=0; $i<$size; $i++) {
if(in_array($expression[$i],MathExpression::$parentheses_open)) {
$tmp[] = $expression[$i];
} elseif(in_array($expression[$i],MathExpression::$parentheses_close)) {
if (count($tmp) == 0 ) {
return false;
}
if(MathExpression::getParenthesesType(array_pop($tmp))
!= MathExpression::getParenthesesType($expression[$i])) {
return false;
}
}
}
if (count($tmp) == 0 ) {
return true;
} else {
return false;
}
}
}
//Mathematical expressions to validate
$tests = array(
'(A1+A2*A3)+A5+(B3^B5)*(C1*((A3/C2)+(B2+C1)))',
'(A1+A2*A3)+A5)*C1+(B3^B5*(C1*((A3/C2)+(B2+C1)))',
'(A1+A2*A3)+A5++(B2+C1)))',
'(A1+A2*A3)+A5+(B3^B5)*(C1*(A3/C2)+(B2+C1))'
);
// running the tests...
foreach($tests as $test) {
$isValid = MathExpression::validate( $test );
echo 'test of: '. $test .'<br>';
var_dump($isValid);
}
you can check and read in detail about the solution here Is there possible to check mathematical expression string?
See also eval. For example, you can do this:
$result = INF;
try {
eval("$result=" + myMathExpression); // Evaluate here
} catch (Exception $e) {
}
if($result != INF) echo("Expression is a valid mathematical expression.");
read more about it there
An extremely simple solution:
Regex number,whitespace,[+,/,*,-,=],whitespace,Substring(recursion here)
will work for any sequence of
1 + 1 + 2 + ... + 1 = 2 + 3 + 4 = 1 * 4 ...
etc.
Obviously would not check if an expression is legit.
As per request, pseudo code:
if Regex(^(([0-9]+)(\s*)([+,/,*,-,=])(\s*)([0-9]+)(\s*)([+,/,*,-,=])(\s*)))
if (recursion())
return True;
else
return False;
else //checking for end point
if Regex(^(([0-9]+)(\s*)([+,/,*,-,=])(\s*)([0-9]+)))
return True;
else
return False;
Maybe a regex with a pattern like this :
^([-+/*]\d+(\.\d+)?)*

Php check if string contains multiple words

I have looked around the internet for something that will do this but it will only work with one word.
I am trying to build a script that will detect a bad username for my site, the bad username will be detected if the username contains any of the words in an array.
Here's the code I made, but failed to work.
$bad_words = array("yo","hi");
$sentence = "yo";
if (strpos($bad_words,$sentence)==false) {
echo "success";
}
If anybody could help me, I would appreciate it.
use
substr_count
for an array use the following function
function substr_count_array( $haystack, $needle ) {
$count = 0;
foreach ($needle as $substring) {
$count += substr_count( $haystack, $substring);
}
return $count;
}
You can use this code:
$bad_words = array("yo","hi");
$sentence = "yo you your";
// break your sentence into words first
preg_match_all('/\w+/', $sentence, $m);
echo ( array_diff ( $m[0], $bad_words ) === $m[0] ) ? "no bad words found\n" :
"bad words found\n";
// returns false or true
function multiStringTester($feed , $arrayTest)
{
$validator = false;
for ($i = 0; $i < count($arrayTest); $i++)
{
if (stringTester($feed, $arrayTest[$i]) === false )
{
continue;
} else
{
$validator = true;
}
}
return $validator;
}
//www.ffdigital.net
I believe a sentence is more than one single word
Try
$badwords = array("yo","hi");
$string = "i am yo this is testing";
$word = array_intersect( $badwords,explode(" " , $string));
if(empty($word))
{
echo "Sucess" ;
}
<?php
function isUserNameCorrect()
{
Foreach($badname in $badnames)
{
if(strstr($badname, $enteredname) == false)
{
return false;
}
}
return true;
}
Maybe this helps
Unfortunately, you can't give an Array to functions strpos/strstr directly.
According to PHP.net comments, to do this you need to use (or create your own if you want) function like this:
function strstr_array($haystack, $needle)
{
if ( !is_array( $haystack ) ) {
return false;
}
foreach ( $haystack as $element ) {
if ( stristr( $element, $needle ) ) {
return $element;
}
}
}
Then, just change strpos to the new function - strstr_array:
$bad_words = array("yo","hi");
$sentence = "yo";
if (strstr_array($bad_words,$sentence)==false) {
echo "success";
}
I'd implement this as follows:
$bad_words = array("yo","hi");
$sentence = "yo";
$valid = true;
foreach ($bad_words as $bad_word) {
if (strpos($sentence, $bad_word) !== false) {
$valid = false;
break;
}
}
if ($valid) {
echo "success";
}
A sentence is valid unless it contains at least one word from $bad_words. Note the strict checking (i.e. !==), without this the check will fail when the result of strpos is 0 instead of false.
You're close. You can do it the following way:
$bad_words = array("yo","hi");
$sentence = "yo";
$match = false;
foreach($bad_words as $bad_word) {
if (strpos($bad_word,$sentence) === false) { # use $bad_word, not $bad_words
$match = true;
break;
}
}
if($match) { echo "success"; }

PHP recursive variable replacement

I'm writing code to recursively replace predefined variables from inside a given string. The variables are prefixed with the character '%'. Input strings that start with '^' are to be evaluated.
For instance, assuming an array of variables such as:
$vars['a'] = 'This is a string';
$vars['b'] = '123';
$vars['d'] = '%c'; // Note that $vars['c'] has not been defined
$vars['e'] = '^5 + %d';
$vars['f'] = '^11 + %e + %b*2';
$vars['g'] = '^date(\'l\')';
$vars['h'] = 'Today is %g.';
$vars['input_digits'] = '*****';
$vars['code'] = '%input_digits';
The following code would result in:
a) $str = '^1 + %c';
$rc = _expand_variables($str, $vars);
// Result: $rc == 1
b) $str = '^%a != NULL';
$rc = _expand_variables($str, $vars);
// Result: $rc == 1
c) $str = '^3+%f + 3';
$rc = _expand_variables($str, $vars);
// Result: $rc == 262
d) $str = '%h';
$rc = _expand_variables($str, $vars);
// Result: $rc == 'Today is Monday'
e) $str = 'Your code is: %code';
$rc = _expand_variables($str, $vars);
// Result: $rc == 'Your code is: *****'
Any suggestions on how to do that? I've spent many days trying to do this, but only achieved partial success. Unfortunately, my last attempt managed to generate a 'segmentation fault'!!
Help would be much appreciated!
Note that there is no check against circular inclusion, which would simply lead to an infinite loop. (Example: $vars['s'] = '%s'; ..) So make sure your data is free of such constructs.
The commented code
// if(!is_numeric($expanded) || (substr($expanded.'',0,1)==='0'
// && strpos($expanded.'', '.')===false)) {
..
// }
can be used or skipped. If it is skipped, any replacement is quoted, if the string $str will be evaluated later on! But since PHP automatically converts strings to numbers (or should I say it tries to do so??) skipping the code should not lead to any problems.
Note that boolean values are not supported! (Also there is no automatic conversion done by PHP, that converts strings like 'true' or 'false' to the appropriate boolean values!)
<?
$vars['a'] = 'This is a string';
$vars['b'] = '123';
$vars['d'] = '%c';
$vars['e'] = '^5 + %d';
$vars['f'] = '^11 + %e + %b*2';
$vars['g'] = '^date(\'l\')';
$vars['h'] = 'Today is %g.';
$vars['i'] = 'Zip: %j';
$vars['j'] = '01234';
$vars['input_digits'] = '*****';
$vars['code'] = '%input_digits';
function expand($str, $vars) {
$regex = '/\%(\w+)/';
$eval = substr($str, 0, 1) == '^';
$res = preg_replace_callback($regex, function($matches) use ($eval, $vars) {
if(isset($vars[$matches[1]])) {
$expanded = expand($vars[$matches[1]], $vars);
if($eval) {
// Special handling since $str is going to be evaluated ..
// if(!is_numeric($expanded) || (substr($expanded.'',0,1)==='0'
// && strpos($expanded.'', '.')===false)) {
$expanded = "'$expanded'";
// }
}
return $expanded;
} else {
// Variable does not exist in $vars array
if($eval) {
return 'null';
}
return $matches[0];
}
}, $str);
if($eval) {
ob_start();
$expr = substr($res, 1);
if(eval('$res = ' . $expr . ';')===false) {
ob_end_clean();
die('Not a correct PHP-Expression: '.$expr);
}
ob_end_clean();
}
return $res;
}
echo expand('^1 + %c',$vars);
echo '<br/>';
echo expand('^%a != NULL',$vars);
echo '<br/>';
echo expand('^3+%f + 3',$vars);
echo '<br/>';
echo expand('%h',$vars);
echo '<br/>';
echo expand('Your code is: %code',$vars);
echo '<br/>';
echo expand('Some Info: %i',$vars);
?>
The above code assumes PHP 5.3 since it uses a closure.
Output:
1
1
268
Today is Tuesday.
Your code is: *****
Some Info: Zip: 01234
For PHP < 5.3 the following adapted code can be used:
function expand2($str, $vars) {
$regex = '/\%(\w+)/';
$eval = substr($str, 0, 1) == '^';
$res = preg_replace_callback($regex, array(new Helper($vars, $eval),'callback'), $str);
if($eval) {
ob_start();
$expr = substr($res, 1);
if(eval('$res = ' . $expr . ';')===false) {
ob_end_clean();
die('Not a correct PHP-Expression: '.$expr);
}
ob_end_clean();
}
return $res;
}
class Helper {
var $vars;
var $eval;
function Helper($vars,$eval) {
$this->vars = $vars;
$this->eval = $eval;
}
function callback($matches) {
if(isset($this->vars[$matches[1]])) {
$expanded = expand($this->vars[$matches[1]], $this->vars);
if($this->eval) {
// Special handling since $str is going to be evaluated ..
if(!is_numeric($expanded) || (substr($expanded . '', 0, 1)==='0'
&& strpos($expanded . '', '.')===false)) {
$expanded = "'$expanded'";
}
}
return $expanded;
} else {
// Variable does not exist in $vars array
if($this->eval) {
return 'null';
}
return $matches[0];
}
}
}
I now have written an evaluator for your code, which addresses the circular reference problem, too.
Use:
$expression = new Evaluator($vars);
$vars['a'] = 'This is a string';
// ...
$vars['circular'] = '%ralucric';
$vars['ralucric'] = '%circular';
echo $expression->evaluate('%circular');
I use a $this->stack to handle circular references. (No idea what a stack actually is, I simply named it so ^^)
class Evaluator {
private $vars;
private $stack = array();
private $inEval = false;
public function __construct(&$vars) {
$this->vars =& $vars;
}
public function evaluate($str) {
// empty string
if (!isset($str[0])) {
return '';
}
if ($str[0] == '^') {
$this->inEval = true;
ob_start();
eval('$str = ' . preg_replace_callback('#%(\w+)#', array($this, '_replace'), substr($str, 1)) . ';');
if ($error = ob_get_clean()) {
throw new LogicException('Eval code failed: '.$error);
}
$this->inEval = false;
}
else {
$str = preg_replace_callback('#%(\w+)#', array($this, '_replace'), $str);
}
return $str;
}
private function _replace(&$matches) {
if (!isset($this->vars[$matches[1]])) {
return $this->inEval ? 'null' : '';
}
if (isset($this->stack[$matches[1]])) {
throw new LogicException('Circular Reference detected!');
}
$this->stack[$matches[1]] = true;
$return = $this->evaluate($this->vars[$matches[1]]);
unset($this->stack[$matches[1]]);
return $this->inEval == false ? $return : '\'' . $return . '\'';
}
}
Edit 1: I tested the maximum recursion depth for this script using this:
$alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEF'; // GHIJKLMNOPQRSTUVWXYZ
$length = strlen($alphabet);
$vars['a'] = 'Hallo World!';
for ($i = 1; $i < $length; ++$i) {
$vars[$alphabet[$i]] = '%' . $alphabet[$i-1];
}
var_dump($vars);
$expression = new Evaluator($vars);
echo $expression->evaluate('%' . $alphabet[$length - 1]);
If another character is added to $alphabet maximum recursion depth of 100 is reached. (But probably you can modify this setting somewhere?)
I actually just did this while implementing a MVC framework.
What I did was create a "find-tags" function that uses a regular expression to find all things that should be replaced using preg_match_all and then iterated through the list and called the function recursively with the str_replaced code.
VERY Simplified Code
function findTags($body)
{
$tagPattern = '/{%(?P<tag>\w+) *(?P<inputs>.*?)%}/'
preg_match_all($tagPattern,$body,$results,PREG_SET_ORDER);
foreach($results as $command)
{
$toReturn[] = array(0=>$command[0],'tag'=>$command['tag'],'inputs'=>$command['inputs']);
}
if(!isset($toReturn))
$toReturn = array();
return $toReturn;
}
function renderToView($body)
{
$arr = findTags($body);
if(count($arr) == 0)
return $body;
else
{
foreach($arr as $tag)
{
$body = str_replace($tag[0],$LOOKUPARRY[$tag['tag']],$body);
}
}
return renderToView($body);
}

Categories