CF7: Array values with regular Expressions inside a PHP Script [duplicate] - php

I have two patterns and i want to search them in a string.
they are like this:
$pattern = '/,3$/'
$pattern = '/^1,/';
actually I want to find strings that start with 1, OR end with ,3
My strings are in this format:
a => 1,2
b => 31,2
c => 4,3
for example a and c are matches!
how can I use preg_match to check this patterns?
tanks for helps.

Try it this way
preg_match("/^1,|,3$/", $string)

/(^1,)|(,3$)/ should work for you.

Just in case some day you will need a non-regex solution, you can use the following startswith and endswith functions:
function startsWith($haystack, $needle) {
// search backwards starting from haystack length characters from the end
return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;
}
function endsWith($haystack, $needle) {
// search forward starting from end minus needle length characters
return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== FALSE);
}
if (startsWith("1,2", "1,") || endsWith("1,2", ",3"))
echo "True1". "\n";
if (startsWith("31,2", "1,") || endsWith("31,2",",3"))
echo "True2". "\n";
if (startsWith("4,3", "1,") || endsWith("4,3",",3"))
echo "True3" . "\n";
Output of the IDEONE demo:
True1
True3

Related

PHP Regex for similarity check

Can you think of any regular expression that resolves these similarities in PHP? The idea is to get a match without considering the last letters.
<?php
$word1 = 'happyness';
$word2 = 'happys';
if (substr($word1, 0, -4) == substr($word2, 0, -1))
{
echo 'same word1';
}
$word1 = 'kisses';
$word2 = 'kiss';
if (substr($word1, 0, -2) == $word2)
{
echo 'same word2';
}
$word1 = 'consonant';
$word2 = 'consonan';
if (substr($word1, 0, -1) == $word2)
{
echo 'same word3';
}
By putting the words together like happys happyness and capturing as many word characters from word 1 as word 2 matches. See this demo at regex101. Use it with the i flag for casless matching.
^(\w+)\w* \1
To use this in PHP with preg_match see this PHP demo at tio.run
preg_match('/^(\w+)\w* \1/i', preg_quote($word1,'/')." ".preg_quote($word2,'/'), $out);
where $out[1] holds the captures or $out would be an empty array if there wasn't a match.
You could use a small helper function, the first function just matches up to the length of the second string, so doesn't care how many characters it truncates. The main code works similar to your code except it uses the length of the second value as the length of the substring to take...
function match( string $a, string $b ) {
return substr($a, 0, strlen($b)) === $b;
}
This function is slightly more complicated as it takes into account a maximum gap length...
function match( string $a, string $b, int $length = 3 ) {
$len = max(strlen($a)-$length, strlen($b));
return substr($a, 0, $len) === $b;
}
So call it something along the lines of
$word1 = 'happyness';
$word2 = 'happys';
if (match($word1,$word2))
{
echo 'same word1';
}
You can use preg_match to match these data with regex as /^word2/ against word1. So regex would check if word1 starts with word2 or not, because of ^ symbol at the start.
It's always better to preg_quote() before matching to escape regex meta characters for accurate results.
<?php
$tests = [
[
'happyness',
'happys'
],
[
'kisses',
'kiss'
],
[
'consonant',
'consonan'
]
];
$filtered = array_filter($tests,function($values){
$values[1] = preg_quote($values[1]);
return preg_match("/^$values[1]/",$values[0]) === 1;
});
print_r($filtered);
Demo: https://3v4l.org/SLf15
You could also do a small function to find the similarity between the given 2 words. It could look like:
function similarity($word1, $word2)
{
$splittedWord1 = str_split($word1);
$splittedWord2 = str_split($word2);
$similarChars = array_intersect_assoc($splittedWord1, $splittedWord2);
return count($similarChars) / max(count($splittedWord1), count($splittedWord2));
}
var_dump(similarity('happyness', 'happys'));
var_dump(similarity('happyness', 'testhappys'));
var_dump(similarity('kisses', 'kiss'));
var_dump(similarity('consonant', 'consonan'));
The result would look like:
float(0.55555555555556)
int(0)
float(0.66666666666667)
float(0.88888888888889)
Based on the resulted percentage you could decide if the given words should be considered the same or not.
I'm not sure regex is the answer here.
You could try similar_text(), which returns the number of similar characters (and optionally sets a percentage value to a variable). Maybe if you consider the last two letters as non-important, you can see if the strlen() - $skippedCharacters is the same as what is matched. For example:
$skippedCharacters = 2;
$word1 = 'kisses';
$word2 = 'kiss';
$match = similar_text($word1, $word2);
if ($match + $skippedCharacters >= strlen($word1))
{
echo 'same word2';
}
You could use the PHP levenshtein function.
The levenshtein() function returns the Levenshtein distance between two strings. The Levenshtein distance is the number of characters you have to replace, insert or delete to transform string1 into string2.
$lev = levenshtein($word1, $word2);
The lower the number the bigger the similarity.

How to check if a string contains certain characters using an array in php

I need to check if a string contains illegal character and I was wondering if there is a way to do it through an array because I have an array character that are allowed. This is in PHP
The array just in case you want to see it:
$MsgAry1 = array("A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z","a","b","c","d",
"e","f","g","h","i","j","k","l","m","n",
"o","p","q","r","s","t","u","v","w","x",
"y","z","1","2","3","4","5","6","7","8",
"9","0",".",",","'","?","!"," ","_","-");
Thanks for any help.
You can use the str_split and in_array functions to do this, as thus:
$MsgAry1 = array("A","B","C"); //Add your actual array here
$testCase = "Hello, World!";
$testCase_arr = str_split($testCase);
foreach($testCase as $test)
{
if(!in_array($test, $MsgAry1))
{
echo "Error! Invalid Character!";
break(); //Or exit();, as needed
}
}
Here's a non-iterative method, which should perform faster than the existing answers that loop.
function containsIllegalChars($testString) {
static $MsgAry1 = array("A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z","a","b","c","d",
"e","f","g","h","i","j","k","l","m","n",
"o","p","q","r","s","t","u","v","w","x",
"y","z","1","2","3","4","5","6","7","8",
"9","0",".",",","'","?","!"," ","_","-");
$foundCount = 0;
str_replace($MsgAry1, '', $testString, $foundCount);
return $foundCount > 0;
}
You can make it even more efficient with your specific set of letters by removing all the uppercase letters, and using str_ireplace.
function containsIllegalChars($testString) {
static $MsgAry1 = array("a","b","c","d",
"e","f","g","h","i","j","k","l","m","n",
"o","p","q","r","s","t","u","v","w","x",
"y","z","1","2","3","4","5","6","7","8",
"9","0",".",",","'","?","!"," ","_","-");
$foundCount = 0;
str_ireplace($MsgAry1, '', $testString, $foundCount);
return $foundCount > 0;
}
You could use something like this, str_split splits the string into characters then you can check each one with in_array:
$MsgAry1 = array("A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z","a","b","c","d",
"e","f","g","h","i","j","k","l","m","n",
"o","p","q","r","s","t","u","v","w","x",
"y","z","1","2","3","4","5","6","7","8",
"9","0",".",",","'","?","!"," ","_","-");
$string = "Hello";
foreach (str_split($string) as $char) {
if (in_array($char, $MsgAry1)) {
echo "Char: ".$char." -> OK";
} else {
echo "Char: ".$char." -> KO";
}
}
$resultarray = preg_replace("/[^A-Za-z0-9]/", "", $MsgAry1);
print_r ($resultarray);
You don't need to loop ...but if you did use a loop, then you'd better use an early return/break so that you aren't doing unnecessary iterations after you've found a disqualifying character.
In a project of my own, I'd prefer to store the regex expression instead of an array of characters -- it's just more concise and direct.
If you must an array of characters, you can avoid the explode and loop by trimming all of the safe characters and check if any characters remain after trimming.
Code: (Demo)
$MsgAry1 = ["A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z","a","b","c","d",
"e","f","g","h","i","j","k","l","m","n",
"o","p","q","r","s","t","u","v","w","x",
"y","z","1","2","3","4","5","6","7","8",
"9","0",".",",","'","?","!"," ","_","-"];
$strings = [
'test',
'1234',
'w0ws3r!',
'##tag##',
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,'?! _-"
];
foreach ($strings as $string) {
echo "$string match: " . var_export(!preg_match("~[^\w.,'?! -]~", $string), true) . "\n";
echo "$string ltrim: " . var_export(!strlen(ltrim($string, implode($MsgAry1))), true) . "\n";
echo "$string after trim: \"" . ltrim($string, "A..Za..z0..9.,'?! _-") . "\"\n---\n";
}
Output:
test match: true
test ltrim: true
test after trim: ""
---
1234 match: true
1234 ltrim: true
1234 after trim: ""
---
w0ws3r! match: true
w0ws3r! ltrim: true
w0ws3r! after trim: ""
---
##tag## match: false
##tag## ltrim: false
##tag## after trim: "##tag##"
---
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,'?! _- match: true
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,'?! _- ltrim: true
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,'?! _- after trim: ""
---
!strlen(ltrim($string, "A..Za..z0..9.,'?! _-")) demonstrates that you can use multiple character ranges in the "character mask" parameter so long as you use .. to indicate each range. I believe this is the most concise, non-regex technique. Again, if the trimmed string has length, then at least one bad character was found.
No matter which technique you prefer, I strongly discourage iterated calls of in_array() -- the performance cost will balloon as the length of the input string increases.

Search a letter in a list of words?

I have an array called 'words' storing many words.
For example:
I have 'systematic', 'سلام','gear','synthesis','mysterious', etc.
NB: we have utf8 words too.
How to query efficiently to see which words include letters 's','m','e' (all of them) ?
The output would be:
systematic,mysterious
I have no idea how to do such a thing in PHP. It should be efficient because our server would suffer otherwise.e.
Use a regular expression to split each string into an array of characters, and use array_intersect() to find out if all the characters in your search array is present in the split array:
header('Content-Type: text/plain; charset=utf8');
$words = array('systematic', 'سلام','gear','synthesis','mysterious');
$search = array('s','m','e');
foreach ($words as $word) {
$char_array = utf8_str_split($word);
$contains = array_intersect($search, $char_array) == $search;
echo sprintf('%s : %s', $word, (($contains) ? 'True' : 'False'). PHP_EOL);
}
function utf8_str_split($str) {
return preg_split('/(?!^)(?=.)/u', $str);
}
Output:
systematic : True
سلام : False
gear : False
synthesis : False
mysterious : True
Demo.
UPDATE: Or, alternatively, you could use array_filter() with preg_match():
$array = array_filter($words, function($item) {
return preg_match('~(?=[^s]*s)(?=[^m]*m)(?=[^e]*e)~u', $item);
});
Output:
Array
(
[0] => systematic
[4] => mysterious
)
Demo.
This worked to me:
$words = array('systematic', 'سلام','gear','synthesis','mysterious');
$letters=array('s','m', 'e');
foreach ($words as $w) {
//print "lets check word $w<br>";
$n=0;
foreach ($letters as $l) {
if (strpos($w, $l)!==false) $n++;
}
if ($n>=3) print "$w<br>";
}
It returns
systematic
mysterious
Explanation
It uses nested foreach: one for the words and the other one for the letters to be matched.
In case any letter is matched, the counter is incremented.
Once the letters loop is over, it checks how many matches were there and prints the word in case it is 3.
Something like this:
$words = array('systematic', 'سلام','gear','synthesis','mysterious');
$result=array();
foreach($words as $word){
if(strpos($word, 's') !== false &&
strpos($word, 'm') !== false &&
strpos($word, 'e') !== false){
$result[] = $word;
}
}
echo implode(',',$result); // will output 'systematic,mysterious'
Your question is wide a little bit.
What I understand from your question that's those words are saved in a database table, so you may filter the words before getting them into the array, using SQL like function.
in case you want to search for a letters in an array of words, you could loop over the array using foreach and each array value should be passed to strpos function.
http://www.php.net/function.strpos
why not use PREG_GREP
$your_array = preg_grep("/[sme]/", $array);
print_r($your_array);
WORKING DEMO

Most efficient way to detect a set of words in a text without regex

Unfortunately, for some strange reason the regex method isn't working for me with UTF-8 (preg_replace + UTF-8 doesn't work on one server but works on another).
What would be the most efficient way to accomplish my goal without using regex?
Just to make it as clear as possible, for the following set of words:
cat, dog, sky
cats would return false
the sky is blue would return true
skyrim would return false
Super short example but it's the way I'd do it without Regex.
$haystack = "cats"; //"the sky is blue"; // "skyrim";
$needles = array("cat", "dog", "sky");
$found = false;
foreach($needles as $needle)
if(strpos(" $haystack ", " $needle ") !== false) {
$found = true;
break;
}
echo $found ? "A needle was found." : "A needle was not found.";
My initial thought is to explode the text on spaces, and then check to see if your words exist in the resulting array. Of course you may have some punctuation leaking into your array that you'll have to consider as well.
Another idea would be to check the strpos of the word. If it's found, test for the next character to see if it is a letter. If it is a letter, you know that you've found a subtext of a word, and to discard this finding.
// Test online at http://writecodeonline.com/php/
$aWords = array( "I", "cat", "sky", "dog" );
$aFound = array();
$sSentence = "I have a cat. I don't have cats. I like the sky, but not skyrim.";
foreach ( $aWords as $word ) {
$pos = strpos( $sSentence, $word );
// If found, the position will be greater than or equal to 0
if ( !($pos >= 0) ) continue;
$nextChar = substr( $sSentence , ( $pos + strlen( $word ) ), 1 );
// If found, ensure it is not a substring
if ( ctype_alpha( $nextChar ) ) continue;
$aFound[] = $word;
}
print_r( $aFound ); // Array ( [0] => I [1] => cat [2] => sky )
Of course the better solution is to determine why you cannot use regex, as these solutions will be nowhere near as efficient as pattern-seeking would be.
If you are simply trying to find if a word is in a string you could store the string in a variable (If printing the string print the variable with the string inside instead) and use "in". Example:
a = 'The sky is blue'
The in a
True

PHP substr after a certain char, a substr + strpos elegant solution?

let's say I want to return all chars after some needle char 'x' from:
$source_str = "Tuex helo babe".
Normally I would do this:
if( ($x_pos = strpos($source_str, 'x')) !== FALSE )
$source_str = substr($source_str, $x_pos + 1);
Do you know a better/smarter (more elegant way) to do this?
Without using regexp that would not make it more elegant and probably also slower.
Unfortunately we can not do:
$source_str = substr(source_str, strpos(source_str, 'x') + 1);
Because when 'x' is not found strpos returns FALSE (and not -1 like in JS).
FALSE would evaluate to zero, and 1st char would be always cut off.
Thanks,
Your first approach is fine: Check whether x is contained with strpos and if so get anything after it with substr.
But you could also use strstr:
strstr($str, 'x')
But as this returns the substring beginning with x, use substr to get the part after x:
if (($tmp = strstr($str, 'x')) !== false) {
$str = substr($tmp, 1);
}
But this is far more complicated. So use your strpos approach instead.
Regexes would make it a lot more elegant:
// helo babe
echo preg_replace('~.*?x~', '', $str);
// Tuex helo babe
echo preg_replace('~.*?y~', '', $str);
But you can always try this:
// helo babe
echo str_replace(substr($str, 0, strpos($str, 'x')) . 'x', '', $str);
// Tuex helo babe
echo str_replace(substr($str, 0, strpos($str, 'y')) . 'y', '', $str);
if(strpos($source_str, 'x') !== FALSE )
$source_str = strstr($source_str, 'x');
Less elegant, but without x in the beginning:
if(strpos($source_str, 'x') !== FALSE )
$source_str = substr(strstr($source_str, 'x'),1);
I needed just this, and striving to keep it on one line for fun came up with this:
ltrim(strstr($source_str, $needle = "x") ?: $source_str, $needle);
The ternary operator was adapted in 5.3 to allow this to work.
Since PHP 5.3, it is possible to leave out the middle part of the ternary operator. Expression expr1 ?: expr3 returns expr1 if expr1 evaluates to TRUE, and expr3 otherwise.
NB. ltrim will trim multiple matching characters at the start of the string.
Append a '-' at the end of $item so it always returns string before '-' even $item doesn't contain '-', because strpos by default returns the position of first occurrence of '-'.
substr($item,0,strpos($item.'-','-'))

Categories