PHP preg_match_all no character or not a certain character - php

Right now the test seems to be working for avoiding the characters that I don't want but it's only returning a count of 2. I know why, I just don't know how to address it. The problem is the last ? is being excluded because the actual match for the 2nd match is (?+ so it's not matching the 3rd since there is no "starting" character for that pattern, it would just be ?).
$pattern = "/([^\w\d'\"`]\?[^\w\d'\"`])/";
$subject = "`test` = ? and `other` = (?+?)";
$count = preg_match_all($pattern, $subject, $matches);
echo "Count: $count\n"; // echoes 2 instead of 3
Basically, I want to count up all the parameters used, so match all ? in the $subject with a ? not surrounded by letters, numbers, quotes, and ticks.
This is the actual pattern that matters:
[^\w\d'\"'`]
Update:
For others, miken32's solution is to convert the above pattern to:
(?=[^\w\d'\"'`])

Try using a lookahead assertion:
$pattern = "/((?<=[^\w\d'\"`])\?(?=[^\w\d'\"`]))/";
It will look ahead without moving the search forward.
Edited to add the lookbehind assertion as well.

Related

regex in php using preg_match

I am trying to make a php file so it can accept word for a regex (a+b)(ab+ba)*
i am using preg_match and so far ive come up with this
$subject = "a+b";
$pattern = '(([a]{1}\+[b]{1})?([ab]{1}\+[ba]{1}))';
preg_match($pattern, $subject, $matches);
print_r($matches);
I am not sure if i completely understand how it works but its been few hours now I am trying to figure out.. how do i make it so it fullfills my condition
I want to match (a+b)(ab+ba)* where the first bracket (a+b) is required and the * on the second bracket (ab+ba) means that there could be zero or multiple instances of it.
so it should work like this
$subject= "(a+b)"
Match
$subject= "(a+b)(ab+ba)"
Match
$subject= "(a+b)(ab+ba)(ab+ba)"
Match
$subject= "(ab+ba)"
No Match
$subject= ""
No Match
In (([a]{1}\+[b]{1})?([ab]{1}\+[ba]{1}))
[a]{1} (1 character in a character class) can be written as a
[b]{1} can be written as b
[ab] (2 characters in a character class) means a or b
I think you have to escape the opening parenthesis \(, or else you would start a capturing group.
If I am not mistaken, this might match what you are looking for:
^\(a\+b\)(?:\(ab\+ba\))*$
The second part is in a non capturing group (?:\(ab\+ba\))* and repeated zero or more times.
Php test ouput

preg_replace - similar patterns

I have a string that contains something like "LAB_FF, LAB_FF12" and I'm trying to use preg_replace to look for both patterns and replace them with different strings using a pattern match of;
/LAB_[0-9A-F]{2}|LAB_[0-9A-F]{4}/
So input would be
LAB_FF, LAB_FF12
and the output would need to be
DAB_FF, HAD_FF12
Problem is, for the second string, it interprets it as "LAB_FF" instead of "LAB_FF12" and so the output is
DAB_FF, DAB_FF
I've tried splitting the input line out using 2 different preg_match statements, the first looking for the {2} pattern and the second looking for the {4} pattern. This sort of works in that I can get the correct output into 2 separate strings but then can't combine the two strings to give the single amended output.
\b is word boundary. Meaning it will look at where the word ends and not only pattern match.
https://regex101.com/r/upY0gn/1
$pattern = "/\bLAB_[0-9A-F]{2}\b|\bLAB_[0-9A-F]{4}\b/";
Seeing the comment on the other answer about how to replace the string.
This is one way.
The pattern will create empty entries in the output array for each pattern that fails.
In this case one (the first).
Then it's just a matter of substr.
$re = '/(\bLAB_[0-9A-F]{2}\b)|(\bLAB_[0-9A-F]{4}\b)/';
$str = 'LAB_FF12';
preg_match($re, $str, $matches);
var_dump($matches);
$substitutes = ["", "DAB", "HAD"];
For($i=1; $i<count($matches); $i++){
If($matches[$i] != ""){
$result = $substitutes[$i] . substr($matches[$i],3);
Break;
}
}
Echo $result;
https://3v4l.org/gRvHv
You can specify exact amounts in one set of curly braces, e.g. `{2,4}.
Just tested this and seems to work:
/LAB_[0-9A-F]{2,4}/
LAB_FF, LAB_FFF, LAB_FFFF
EDIT: My mistake, that actually matches between 2 and 4. If you change the order of your selections it matches the first it comes to, e.g.
/LAB_([0-9A-F]{4}|[0-9A-F]{2})/
LAB_FF, LAB_FFFF
EDIT2: The following will match LAB_even_amount_of_characters:
/LAB_([0-9A-F]{2})+/
LAB_FF, LAB_FFFF, LAB_FFFFFF...

PHP RexExp match and substitute

I am testing RegExp with online regexr.com tool. I will test string with multiple cases, but I can't get substitution to work.
RexEx for matching string is:
/^[0-9]{1,3}[0-9]{6,7}$/
Which matches local mobile number in my country like this:
0921234567
But then I want to substitute number in this way: add "+" sign, add my country code "123", add "." sign, and then finaly, add matched number with stripped leading zero.
Final number will be:
+385.921234567
I have basic idea to insert matched string, but I am not sure how prepend characters, and strip zero from matched string in following substitution pattern:
\+$&\n\t
I will use PHP preg_replace function.
EDIT:
As someone mentioned wisely, there is posibility that there will be one, two or none of zeros, but I will create separate test cases with regex just testing number of zeroes. Doing so in one regex seems to complicated for now.
Possible numbers will be:
0921234567
00111921234567
Where 111 is country code. I know that some country codes consist of 2 or 3 digits, but I will create special cases, for most country codes.
You can use this preg_replace to strip optional zeroes from start of your mobile #:
$str = preg_replace('~^0*(\d{7,9})$~', '+385.$1', $str);
^[0-9]([0-9]{1,2}[0-9]{6,7})$
You just need to add groups.Replace by +385.$1.See demo.
https://regex101.com/r/cJ6zQ3/22
$re = "/^[0-9]([0-9]{1,2}[0-9]{6,7})$/m";
$str = "0921234567\n";
$subst = "+385.$1";
$result = preg_replace($re, $subst, $str);
I would use a 2-step solution:
Check if we match the main regex
Replace the number by pre-pending + + country code + . + number without leading zeros.
PHP code:
$re = "/^[0-9]{7,10}$/";
$str = "0921234567";
if (preg_match($re, $str, $match)) {
echo "+385." . preg_replace('/^0+/', '', $match[0]);
}
Note that splitting out character class in your regex pattern makes no sense when not using capture groups. ^[0-9]{7,10}$ is the same then as ^[0-9]{1,3}[0-9]{6,7}$, meaning match 7 to 10 digits from start to end of the string.
Leading zeros are easily trimmed from the start with /^0+/ regex.

Regex unicode - route codeignite

I am working on getting the regex to work but now I am starting to go in circles.
This regex would be used in the codeigniter for the routing purposes, something like:
$route['([\p{Ll}\p{Cyrillic}0-9\s\-]+)-(\d+).html'] = "blog/$2";
I've got a regex that does what I need to:
$pattern = "/^[\p{Ll}0-9\s\-]+$/u";
But for some reason it doesn't want to work in the patten bellow
$str="asdбв-37.html";
$pattern = "#^([\p{Ll}\p{Cyrillic}0-9\s\-]+)-(\d+).html#";
$result = (bool) preg_match($pattern, $str);
if($result)
echo "$str is composed of Cyrillic and alphanumeric characters\n";
My end target is to check that any character, from any language, is written in the lower case, that is why I have used \p{Ll}
The pattern which is working but for asdбв-37.html doesn't allow periods. Try adding them in:
^[a-zA-Z\p{Cyrillic}0-9\s.-]+$
[Also, you don't need to escape the - if it's at the end or beginning of a character class to change its meaning to literal.]

Match only the first set of numbers in a string

I need to retrieve the first set of numbers from a string, but I'm not sure how.
I have the following, which I was expecting to pick each set of numbers so that I could then pick the first key from the $matches array, but it literally matches only the first number.
In this example I'd be looking for '123'. Can someone please let me know how to do this with RegEx (or a better way if RegEx is not best for the job). Thanks.
$e = 'abc 123,456,def, 789-ab-552'; // Just a random example
$pattern = "/[0-9]/";
preg_match($pattern, $e, $matches);
You must add a quantifier:
$pattern = "/[0-9]+/";
+ means one or more
You can find an ajax regex tester for php here and more informations about regular expressions here.

Categories