Regex: match single equal sign with negative lookahead = - php

I am building something that requires the user to input conditions and then I will parse it with PHP. I want to build a preg_replace that replaces = with == but == remains untouched.
Examples
a=b => a==b
a==b => a==b
a = b => a == b
a == b => a == b
So basically if a user forgets that the condition needs == instead of =, the system will allow that too.

You can use this regex,
(?<![=!])=(?![=!])
Which ensures a = will only be selected if it is not preceded or followed by a = and replace it by ==
Demo
Sample PHP codes,
$arr = array("a=b", "a==b", "a = b", "a == b", "a!=b");
foreach($arr as $s) {
echo $s, ' --> ', preg_replace('/(?<![=!])=(?![=!])/', '==', $s) , "\n";
}
Prints,
a=b --> a==b
a==b --> a==b
a = b --> a == b
a == b --> a == b
a!=b --> a!=b

Another option is to use positive lookbehind to assert what is on the left is either a word character \w or a whitespace character \s
(?<=[\w\s])=+
Regex demo | Php demo
For example:
$result = preg_replace('/(?<=[\w ])=+/', '==', $str)

You could get the desired result by doing the following :
$string = "a == b" ;
$string = str_replace('==', '=', $string);
$string = str_replace('=', '==', $string);
var_dump($string);
By replacing all == to = and then replacing all = to ==

Related

PHP remove specific character and number from beginning of string

I want to remove brackets and number from beginning of string but problem is brackets and number is coming only specific string not all.
for example following is my string.
1) [4] Mustangs 8u
2) Pool a First Place
3) Team slect
4) [3] In pruduct
so above you can see only 1 and 4 string have number with brackets at beginning of string so i want to only remove that if that found in string.
I write following code but is not work.
<?php
foreach ($grouped as $round_number => $group) {
$team_1_name = $group->team_1_name;
$new_str = preg_replace('/^([0-9]* \w+ )?(.*)$/', '$2', $team_1_name);
$date = date ('F d, Y g:iA', $unix_time);
}
?>
Try regular expression /^(\[[0-9]\]?\s?)/ as:
$new_str = preg_replace('/^(\[[0-9]\]?\s?)/', '$2', $team_1_name);
For reference: regexr
In case your numbers are multi digit (i.e. '[11] In pruduct')...
echo preg_replace('/^(\[\d*\]?\s?)/', '$2', $team_1_name);
Instead regex you can use ltrim() with a character mask. If your strings never start with a number:
$new_str = ltrim($team_1_name, "0123456789[] ");
else you could check if the first char is a bracket:
$new_str = $team_1_name[0] == '[' ? ltrim($team_1_name, '0123456789[] ') : '';

Combine Multiple Regex into One

I am trying to write a code to hyphenate a string into latin verses. There are a few constraints to it which I have taken care of, however I do not get the desired output. My code is given below :
<?php
$string = "impulerittantaenanimis caelestibusirae";
$precedingC = precedingConsonant($string);
$xrule = xRule($precedingC);
$consonantc = consonantCT($xrule);
$consonantp = consonantPT($consonantc);
$cbv = CbetweenVowels($consonantp);
$tv = twoVowels($cbv);
echo $tv;
function twoVowels($string)
{
return preg_replace('/([aeiou])([aeiou])/', '$1-$2', $string);
}
function CbetweenVowels($string)
{
return preg_replace('/([aeiou])([^aeiou])([aeiou])/', '$1-$2$3', $string);
}
function consonantPT($string)
{
return preg_replace('/([^aeiou]p)(t[aeiou])/', '$1-$2', $string);
}
function consonantCT($string)
{
return preg_replace('/([^aeiou]c)(t[aeiou])/', '$1-$2', $string);
}
function precedingConsonant($string)
{
$arr1 = str_split($string);
$length = count($arr1);
for($j=0;$j<$length;$j++)
{
if(isVowel($arr1[$j]) && !isVowel($arr1[$j+1]) && !isVowel($arr1[$j+2]) && isVowel($arr1[$j+3]))
{
$pc++;
}
}
function strAppend2($string)
{
$arr1 = str_split($string);
$length = count($arr1);
for($i=0;$i<$length;$i++)
{
$check = $arr1[$i+1].$arr1[$i+2];
$check2 = $arr1[$i+1].$arr1[$i+2].$arr1[$i+3];
if($check=='br' || $check=='cr' || $check=='dr' || $check=='fr' || $check=='gr' || $check=='pr' || $check=='tr' || $check=='bl' || $check=='cl' || $check=='fl' || $check=='gl' || $check=='pl' || $check=='ch' || $check=='ph' || $check=='th' || $check=='qu' || $check2=='phl' || $check2=='phr')
{
if(isVowel($arr1[$i]) && !isVowel($arr1[$i+1]) && !isVowel($arr1[$i+2]) && isVowel($arr1[$i+3]))
{
$updatedString = substr_replace($string, "-", $i+1, 0);
return $updatedString;
}
}
else
{
if(isVowel($arr1[$i]) && !isVowel($arr1[$i+1]) && !isVowel($arr1[$i+2]) && isVowel($arr1[$i+3]))
{
$updatedString = substr_replace($string, "-", $i+2, 0);
return $updatedString;
}
}
}
}
$st1 = $string;
for($k=0;$k<$pc;$k++)
{
$st1 = strAppend2($st1);
}
return $st1;
}
function xRule($string)
{
return preg_replace('/([aeiou]x)([aeiou])/', '$1-$2', $string);
}
function isVowel($ch)
{
if($ch=='a' || $ch=='e' || $ch=='i' || $ch=='o' || $ch=='u')
{
return true;
}
else
{
return false;
}
}
function isConsonant($ch)
{
if($ch=='a' || $ch=='e' || $ch=='i' || $ch=='o' || $ch=='u')
{
return false;
}
else
{
return true;
}
}
?>
I believe if I combine all these functions it will result in the desired output. However I will specify my constraints below :
Rule 1 : When two or more consonants are between vowels, the first consonant is joined to the preceding vowel; for example - rec-tor, trac-tor, ac-tor, delec-tus, dic-tator, defec-tus, vic-tima, Oc-tober, fac-tum, pac-tus,
Rule 2 : 'x' is joined to the preceding vowel; as, rex-i.
However we give a special exception to the following consonants - br, cr, dr, fr, gr, pr, tr; bl, cl, fl, gl, pl, phl, phr, ch, ph, th, qu. These consonants are taken care by adding them to the later vowel for example - con- sola-trix
n- sola-trix.
Rule 3 : When 'ct' follows a consonant, that consonant and 'c' are both joined to the first vowel for example - sanc-tus and junc-tum
Similarly for 'pt' we apply the same rule for example - scalp-tum, serp-tum, Redemp-tor.
Rule 4 : A single consonant between two vowels is joined to the following vowel for example - ma-ter, pa-ter AND Z is joined to the following vowel.
Rule 5 : When two vowels come together they are divided, if they be not a diphthong; as au-re-us. Diaphthongs are - "ae","oe","au"
If you look carefully at each rule, you can see that all involve a vowel at the beginning or a preceding vowel. Once you realize that, you can try to build a single pattern putting [aeiou] in factor at the beginning:
$pattern = '~
(?<=[aeiou]) # each rule involves a vowel at the beginning (also called a
# "preceding vowel")
(?:
# Rule 2: capture particular cases
( (?:[bcdfgpt]r | [bcfgp] l | ph [lr] | [cpt] h | qu ) [aeiou] x )
|
[bcdfghlmnp-tx]
(?:
# Rule 3: When "ct" follows a consonant, that consonant and "c" are both
# joined to the first vowel
[cp] \K (?=t)
|
# Rule 1: When two or more consonants are between vowels, the first
# consonant is joined to the preceding vowel
\K (?= [bcdfghlmnp-tx]+ [aeiou] )
)
|
# Rule 4: a single consonant between two vowels is joined to the following
# vowel
(?:
\K (?= [bcdfghlmnp-t] [aeiou] )
|
# Rule 2: "x" is joined to the preceding vowel
x \K (?= [a-z] | (*SKIP)(*F) )
)
|
# Rule 5: When two vowels come together they are divided, if they not be a
# diphthong ("ae", "oe", "au")
\K (?= [aeiou] (?<! a[eu] | oe ) )
)
~xi';
This pattern is designed to only match the position where to put the hyphen (except for particular cases of Rule 2), that's why it uses a lot of \K to start the match result at this position and lookaheads to test what follows without matching characters.
$string = <<<EOD
Aeneadum genetrix, hominum diuomque uoluptas,
alma Uenus, caeli subter labentia signa
quae mare nauigerum, quae terras frugiferentis
concelebras, per te quoniam genus omne animantum
EOD;
$result = preg_replace($pattern, '-$1', $string);
Ae-ne-a-dum ge-ne-trix, ho-mi-num di-u-om-qu-e u-o-lup-tas,
al-ma U-e-nus, cae-li sub-ter la-ben-ti-a sig-na
qu-ae ma-re nau-i-ge-rum, qu-ae ter-ras fru-gi-fe-ren-tis
con-ce-leb-ras, per te qu-o-ni-am ge-nus om-ne a-ni-man-tum
Note that I didn't include several letters like k, y and z that don't exist in the latin alphabet, feel free to include them if you need to handle translated greek words or other.

php - find match in string

I'm trying to work out how to find a match in a string.
I'm looking for a match on any of the following - = ? [] ~ # ! 0 - 9 A-Z a-z and I need to know what its matched on .
Eg: matched on !, or matched on = and # and ?
Normally I'd use this:
$a = 'How are you?';
if (strpos($a, 'are') !== false) {
echo 'true';
}
However I'm not sure how to do that so it looks up the characters needed.
Also where I may have [], It could be [] or [xxxx] where xxxx could be any number of alpha numeric characters.
I need to match and any of the characters listed, return the characters so I know what was matched and if the [] contain any value return that as well.
Eg:
$a = 'DeviceLocation[West12]';
Would return: $match = '[]'; $match_val= 'West12';
$a = '#=Device';
Would return:$match = '#,=';
$a= '?[1234]=#Martin';
Would return: $match = '?, [], =, #'; $match_val= '1234';
Can any one advise how I can do this.
Thanks
Well, that requirements are a bit vague, but that is what I deduced:
1) if there is an alphanumeric string inside square brackets get it as a separate value
2) all other mentioned chars should be matched one by one and then imploded.
You may use the following regex to get the values you need:
$re = '#\[([a-zA-Z0-9]+)\]|[][=?~#!]#';
Details:
\[ - a [
([a-zA-Z0-9]+) - Group 1 value capturing 1 or more alphanumeric symbols
\] - a closing ]
| - or
[][=?~#!] - a single char, one of the defined chars in the set.
See the regex demo. The most important here is the code that gets the matches (feel free to adapt):
$re = '#\[([a-zA-Z0-9]+)\]|[][=?~#!]#';
$strs =array('DeviceLocation[West12]', '#=Device', '?[1234]=#Martin');
foreach ($strs as $str) {
preg_match_all($re, $str, $matches, PREG_SET_ORDER);
$results = array();
$match_val = "";
foreach ($matches as $m) {
if (!empty($m[1])) {
$match_val = trim($m[1], "[]");
array_push($results, "[]");
} else {
array_push($results, $m[0]);
}
}
echo "Value: " . $match_val . "\n";
echo "Symbols: " . implode(", ", $results);
echo "\n-----\n";
}
See the PHP demo
Output:
Value: West12
Symbols: []
-----
Value:
Symbols: #, =
-----
Value: 1234
Symbols: ?, [], =, #
-----
Please use Regular Expressions, e.g using preg_match
Try this
It will match the string in []
preg_match_all("/\[([^\]]*)\]/", $text, $matches);
And this will match string after ? and #=
preg_match_all("/^#=(\S+)|\?(.*)/", $text, $matches);
var_dump($matches);
You need regular expressions to check for any text inside another with different properties, here is a simple tutorial on that link.

php find a substring only if it's not part of another substring

I know how to find substrings using strpos, but I want to return True only if the letter t appears in a string, but not if that t is followed by "he". For example...
$str="The lion and dog are hungry"
The result would be Does not contain t because the only t in the string was part of the word "The".
$str="Their bedroom is ugly" should also return false because "Their" starts with T H E and there's not other t in the string.
$str="The cat and the dog are hungry" would result in Yes, this string contains a t because there's a t in CAT.
You need a negative lookbehind regex:
/t(?!h(?:e|is))/i
See the regex demo
Pattern details:
t - a literal char t
(?!h(?:e|is)) - a negative lookbehind that checks if its pattern matches the string after the current location and failing the match (returning false) if the match occurs:
h - a literal h
(?:e|is) - either e or is (the (?:...|...) is a non-capturing group that does not keep submatches in the memory containing a | alternation operator)
/i - case insensitive modifier making the regex match in a case insensitive way.
Basically, this is a more efficient version of a t(?!he|his) regex (t not followed with he or his).
PHP demo:
$re = '/t(?!h(?:e|is))/i';
if (preg_match($re,'The cat and the dog are hungry'))
echo 'true';
else
echo 'false';
Try this
<?php
$a = 'Their bedroom is ugly';
if (preg_match('/t(?!he)(?!his)/i',$a))
echo 'true';
else
echo 'false';
You can use strpos to check to see if there's an 'he' after all the 't's you find:
<?php
$offest = 0;
$string = "the t the";
$result = 'No, this string does not contain t';
while ($pos1 = strpos($string,'t', $offset)) {
if ($pos2 = strpos($string,'the',$offset) {
if ($pos1 != $pos2) {
$result = 'Yes, this string contains t';
} else {
$offset = pos1;
}
} else {
$result = 'Yes, this string contains t';
}
}
echo $result;
but that's not the most efficient way to do it. IMHO the best thing to do would be to use a Regex
$string = "the t the";
$result = 'no';
if (preg_match('/[tT][^Hh]/')) {
$result = 'yes';
}
You can also use negative lookahead (a personal favorite technique):
$string = "the t the";
$result = 'no';
if (preg_match('/t(?!he)/i')) {
$result = 'yes';
}

PHP (Regex) Check if a string contains at least 4 digits + 2 letters

I would check a string if contains at least:
2 letters (a-z) CASE INSENSITIVE
4 digits (0-9)
the order is not important. It could be a1234b, abcd1234, 4444aa etc etc.
My actual regex is
if (preg_match("/[a-z][^a-z]*[a-z]*[0-9]/i",$string)) {
echo 'secure';
$continue = true;
}
and it doesn't function if string start with a digit. Thank you
^(?=(?:.*[a-zA-Z]){2})(?=(?:.*[0-9]){4})\w+$
You can use lookahead here to apply the conditions.See demo.
https://regex101.com/r/vV1wW6/22
$re = "/^(?=(?:.*[a-zA-Z]){2})(?=(?:.*[0-9]){4})\\w+$/m";
$str = "a1234b\nabcd1234\n4444aa\n12\n12a\n12aa22";
preg_match_all($re, $str, $matches);
You can use a human-readable check like this:
Remove all non-letters (\P{L} for letters and \P{M} for non-diacritics) and if the resulting string length is less than 2, return false
Remove all non-digits (\D) and if the resulting string length is less than 4, return false.
As for
it doesn't function if string start with a digit
You can add an if (preg_match('/^\D/', $str)) where ^\D means starts with a non-digit.
PHP code:
if (preg_match('/^\D/', $str)) {
if (mb_strlen(preg_replace('/\D/', '', $str), 'UTF8') < 4 ||
mb_strlen(preg_replace('/[\P{L}\P{M}]/u', '', $str), 'UTF8') < 2) {
echo "Invalid";
}
else
{
echo "Valid";
}
}
See IDEONE demo
Note that to count the length of a Unicode string you need mb_strlen function.
You can try this pattern (\b[a-zA-Z]+\d{4}[a-z]?|\b[a-zA-Z]+\d{4}|\b\d{4}[a-zA-Z]+)
See demo here https://regex101.com/r/uJ0vD4/8
Input
a1234b, abcd1234, 4444aa, 33333, ab555, aac3566
Output
a1234b, abcd1234, 4444aa, aac3566
^(?=(?:.*[0-9]){4})\w+$ works for this case
for PHP:
$re = "/^(?=(?:.*[0-9]){4})\\w+$/m";
$str = "a1234b\naaa32233\n";
preg_match_all($re, $str, $matches);
for javascript:
var re = /^(?=(?:.*[0-9]){4})\w+$/gm;
var str = 'a1234b\naaa32233\n';
var m;
while ((m = re.exec(str)) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}

Categories