RegEx to handle Alphanumeric Input - PHP - php

I have this code.
<?php
$USClass = "3/312";
$USClass = preg_replace_callback('~[\d.]+/[\d.]+~', function ($matches) {
$parts = explode('/', $matches[0]);
return $parts[1] . ',' . $parts[0];
}, $USClass);
echo $USClass;
?>
It prints 312,3 which is what I wanted.
However, if I give an input like D12/336 then it does not work. I want it to print 336,D12
How can I do it? and What is wrong with my current code which is not handling this Alphanumeric? Is it because I used \d ?
EDIT:
I want it to handle inputs like this as well
148/DIG.111
then the output should be DIG.111,148

Yes \d does only contain digits.
You can try \w instead this is alphanumeric, but additionally it includes also _
To be Unicode you can go for
~[\pL\d.]+/[\pL\d.]+~u
\pL is a Unicode code point with the property "Letter"
The u at the end turn on the UTF-8 mode that is needed to use this feature
See http://www.php.net/manual/en/regexp.reference.unicode.php
Other solution
I think you ar e doing this a bit complicated. It would be simplier if you would make use of capturing groups.
Try this:
$in = "148/DIG.111";
preg_match_all('~([\w.]+)/([\w.]+)~', $in, $matches);
echo $matches[2][0] . ',' . $matches[1][0];
Explanation:
([\w.]+)/([\w.]+)
^^^^^^^^ ^^^^^^^^
Group 1 Group 2
Because of the brackets the matched substring is stored in the array $matches.
See here for more details on preg_match_all

With a simple preg_replace:
$USClass = "148/DIG.111";
$USClass = preg_replace('#(.+?)/(.+)#', "$2,$1", $USClass);
echo $USClass;
output:
DIG.111,148

Related

how to remove everything before second occurance of underscore

I couldn't find the solution using search.
I am looking for a php solution to remove all character BEFORE the second occurance of and underscore (including the underscore)
For example:
this_is_a_test
Should output as:
a_test
I currently have this code but it will remove everything after the first occurance:
preg_replace('/^[^_]*.s*/', '$1', 'this_is_a_test');
Using a slightly different approach,
$s='this_is_a_test';
echo implode('_', array_slice( explode( '_', $s ),2 ) );
/* outputs */
a_test
preg_replace('/^.*_.*_(.*)$/U', '$1', 'this_is_a_test');
Note the U modifier which tells regex to take as less characters for .* as possible.
You can also use explode, implode along with array_splice like as
$str = "this_is_a_test";
echo implode('_',array_splice(explode('_',$str),2));//a_test
Demo
Why go the complicated way? This is a suggestion though using strrpos and substr:
<?php
$str = "this_is_a_test";
$str_pos = strrpos($str, "_");
echo substr($str, $str_pos-1);
?>
Try this one.
<?php
$string = 'this_is_a_test';
$explode = explode('_', $string, 3);
echo $explode[2];
?>
Demo
I'm still in favor of a regular expression in this case:
preg_replace('/^.*?_.*?_/', '', 'this_is_a_test');
Or (which looks more complex here but is easily adjustable to N..M underscores):
preg_replace('/^(?:.*?_){2}/', '', 'this_is_a_test');
The use of the question mark in .*? makes the match non-greedy; and the pattern has been expanded from the original post to "match up through" the second underscore.
Since the goal is to remove text the matched portion is simply replaced with an empty string - there is no need for a capture group or to use such as the replacement value.
If the input doesn't include two underscores then nothing is removed; such can be adjusted, very easily with the second regular expression, if the rules are further clarified.

Removing all characters and numbers except last variable with dash symbol

Hi I want to remove a characters using preg_replace in php so i have this code here which i want to remove the whole characters, letters and numbers except the last digit(s) which has dash(-) symbol followed by a digits so here's my code.
echo preg_replace('/(.+)(?=-[0-9])|(.+)/','','asdf1245-10');
I expect the result will be
-10
the problem is above is not working very well. I checked the pattern using http://www.regextester.com/ it seems like it works, but on the other side http://www.phpliveregex.com/ doesn't work at all. I don't know why but anyone who can help to to figure it out?
Thanks a lot
Here is a way to go:
echo preg_replace('/^.+?(-[0-9]+)?$/','$1','asdf1245-10');
Output:
-10
and
echo preg_replace('/^.+?(-[0-9]+)?$/','$1','asdf124510');
Output:
<nothing>
My first thinking is to use explode in this case.. make it simple like the following code.
$string = 'asdf1245-10';
$array = explode('-', $string);
end($array);
$key = key($array);
$result = '-' . $array[$key];
$result => '-10';
An other way:
$result = preg_match('~\A.*\K-\d+\z~', $str, $m) ? $m[0] : '';
pattern details:
\A # start of the string anchor
.* # zero or more characters
\K # discard all on the left from match result
-\d+ # the dash and the digits
\z # end of the string anchor
echo preg_replace('/(\w+)(-\w+)/','$2', 'asdf1245-10');

Using preg_replace to modify first space, but not inside a group of words using PHP

I would like to replace commas and potential spaces (i.e. that user can type or not) of an expression using preg_replace.
$expression = 'alfa,beta, gamma gmm, delta dlt, epsilon psln';
but I was unable to format the output as I want:
'alfa|beta|gamma gmm|delta dlt|epsilon psln'
Amongst others I tried this:
preg_replace (/,\s+/, '|', $expression);
and although it was the closest I got, it's not yet right. With code above I receive:
alfa,beta|gamm|gmm|delt|dlt|epsilo|psl|
Then I tried this (with | = OR):
preg_replace (/,\s+|,/, '|', $expression);
and although I solved the problem with the comma, it is still wrong:
alfa|beta|gamm|gmm|delt|dlt|epsilo|psl|
What should I do to only delete space after comma and not inside the word-group?
Many thanks in advance!
Use ,\s* instead of ,\s+ and replace the matched characters with | symbol. If you use ,\s+, it matches the commas and the following one or more spaces but it forgot the commas which are alone. By making the occurrence of spaces to zero or more times, it would also match the commas which are alone.
DEMO
Code:
<?php
$string = 'alfa,beta, gamma gmm, delta dlt, epsilon psln';
$pattern = "~,\s*~";
$replacement = "|";
echo preg_replace($pattern, $replacement, $string);
?>
Output:
alfa|beta|gamma gmm|delta dlt|epsilon psln
How about using regular PHP functions to achieve this?
<?php
$expression = 'alfa,beta, gamma gmm, delta dlt, epsilon psln';
$pieces = explode(',', $expression);
foreach($pieces as $k => $v)
$pieces[$k] = trim($v);
$result = implode('|', $pieces);
echo $result;
?>
Output:
alfa|beta|gamma gmm|delta dlt|epsilon psln
This will distinguish between spaces at start/end of piece and spaces in pieces.

How to manipulate a string so I can make implicit multiplication explicit in a math expression?

I want to manipulate a string like "...4+3(4-2)-...." to become "...4+3*(4-2)-....", but of course it should recognize any number, d, followed by a '(' and change it to 'd*('. And I also want to change ')(' to ')*(' at the same time if possible. Would nice if there is a possibility to add support for constants like pi or e too.
For now, I just do it this stupid way:
private function make_implicit_multiplication_explicit($string)
{
$i=1;
if(strlen($string)>1)
{
while(($i=strpos($string,"(",$i))!==false)
{
if(strpos("0123456789",substr($string,$i-1,1)))
{
$string=substr_replace($string,"*(",$i,1);
$i++;
}
$i++;
}
$string=str_replace(")(",")*(",$string);
}
return $string;
}
But I Believe this could be done much nicer with preg_replace or some other regex function? But those manuals are really cumbersome to grasp, I think.
Let's start by what you are looking for:
either of the following: ((a|b) will match either a or b)
any number, \d
the character ): \)
followed by (: \(
Which creates this pattern: (\d|\))\(. But since you want to modify the string and keep both parts, you can group the \( which results in (\() making it worse to read but better to handle.
Now everything left is to tell how to rearrange, which is simple: \\1*\\2, leaving you with code like this
$regex = "/(\d|\))(\()/";
$replace = "\\1*\\2";
$new = preg_replace($regex, $replace, $test);
To see that the pattern actually matches all cases, see this example.
To recognize any number followed by a ( OR a combination of a )( and place an asterisk in between them, you can use a combination of lookaround assertions.
echo preg_replace("/
(?<=[0-9)]) # look behind to see if there is: '0' to '9', ')'
(?=\() # look ahead to see if there is: '('
/x", '*', '(4+3(4-2)-3)(2+3)');
The Positive Lookbehind asserts that what precedes is either a number or right parentheses. While the Positive Lookahead asserts that the preceding characters are followed by a left parentheses.
Another option is to use the \K escape sequence in replace of the Lookbehind. \K resets the starting point of the reported match. Any previously consumed characters are no longer included ( throws away everything that it has matched up to that point. )
echo preg_replace("/
[0-9)] # any character of: '0' to '9', ')'
\K # resets the starting point of the reported match
(?=\() # look ahead to see if there is: '('
/x", '*', '(4+3(4-2)-3)(2+3)');
Your php code should be,
<?php
$mystring = "4+3(4-2)-(5)(3)";
$regex = '~\d+\K\(~';
$replacement = "*(";
$str = preg_replace($regex, $replacement, $mystring);
$regex1 = '~\)\K\(~';
$replacement1 = "*(";
echo preg_replace($regex1, $replacement1, $str);
?> //=> 4+3*(4-2)-(5)*(3)
Explanation:
~\d+\K\(~ this would match the one or more numbers followed by a (. Because of \K it excludes the \d+
Again it replaces the matched part with *( which in turn produces 3*( and the result was stored in another variable.
\)\K\( Matches )( and excludes the first ). This would be replaced by *( which in turn produces )*(
DEMO 1
DEMO 2
Silly method :^ )
$value = '4+3(4-2)(1+2)';
$search = ['1(', '2(', '3(', '4(', '5(', '6(', '7(', '8(', '9(', '0(', ')('];
$replace = ['1*(', '2*(', '3*(', '4*(', '5*(', '6*(', '7*(', '8*(', '9*(', '0*(', ')*('];
echo str_replace($search, $replace, $value);

PHP replacement is empty, or not replaced

Well im trying to replace the first number in a string in PHP, but not behaves as spected.
$str = 'A12:B17';
$newvalue = '987';
echo preg_replace('/(^[A-Za-z])\d+(.*)/', '\1'.$newvalue.'\2', $str);
The problem is \1 is well replaced when i put it alone, but when i put $newvalue and \2 the first \1 is ignored
input1:
echo preg_replace('/(^[A-Za-z])\d+(.*)/', '\1'.$newvalue.'\2', $str);
output1:
87:B17 // dissapears first character :/
input2:
echo preg_replace('/(^[A-Za-z])\d+(.*)/', '\1'.$newvalue.'\2', $str);
output2:
A
desired result:
A987:B17
NOTE: I need a regex solution, this applies to other similar problems.
You can use:
echo preg_replace('/(^[A-Za-z])\d+(.*)/', '${1}' . $newvalue . '${2}', $str);
//=> OUTPUT: A987:B17
Problem is that in your code back reference variable \1 is becoming \1987 and that's why showing empty value. ${1} keeps it separate from 987 and hence values are properly replaced.
anubhava's answer is great, but you could also use a lookbehind assertion like this:
echo preg_replace('/(?<=^[A-Za-z])\d+/', $newvalue, $str);
The lookbehind ensures that the matched string (\d+) immediately follows a string which matches the pattern, ^[A-Za-z]. However, unlike your original, the portion of the string which matches the lookbehind is not captured in the match, so the entire match is 12.
And just to provide yet another solution, you could also use a callback:
echo preg_replace_callback('/(^[A-Za-z])\d+/', function($m) use (&$newvalue) {
return $m[1].$newvalue;
}, $str);

Categories