Regex preg_match issue with commas - php

This is my code to pre_match when an amount looks like this: $ 99.00 and it works
if (preg_match_all('/[$]\s\d+(\.\d+)?/', $tout, $matches))
{ $tot2 = $matches[0];
$tot2 = preg_replace("/\\\$/", '', $tot2);}
I need to do the same thing for a amount that looks like this (with a comma): $ 99,00
Thank you for your help (changing dot for comma do not help, there is an "escape" thing I do not understand...
Idealy I need to preg_match any number that looks like an amount with dot or commas and with or without dollar sign before or after (I know, it's a lot to ask :) since on the result form I want to scan there are phone and street numbers...
UPDATE (For some reason I cannot comment on replies) : To test properly, I need to preg_replace the comma by a dot (since we are dealings with sums, I don't think calculations can be done on numbers with commas in it).
So to clarify my question, I should say : I need to transform, let's say "$ 200,24" to "200.24". (could be amounts bettween 0.10 to 1000.99) :
$tot2 = preg_replace("/\\\$/", '', $tot2);}
(this code just deals with the $ (it works), I need adaptation to deal also with the change of (,) for (.))

No, using , in place of \. works perfectly fine.
It's just that your input does not contain a space between dollar sign and amount $ 99,00 like your .-using source did.
Make the \s optional.

How about:
$str='$ 200,24';
echo str_replace(array('$',',',' '), array('','.',''), $str);
output:
200.24

replace the . character with a character class [,.] which includes both a dot(.) and comma(,)
'/[$]\s\d+([.,]\d+)?/'
edit: comment is correct, regex fixed.

Related

Using str_replace to replace a character and then 1 character after that

I have queried a Minecraft server and this is what it looks like
"§f§6§lMINE§b§lHEROES §7[1.7-1.14+] §b20% OFF SALE §e§lPRISON SERVER RESET §f- §9§lVIP OUT NOW!"
So I tried using str_replace to get rid of these §.
str_replace('§', '', $server->name)
Now it looks like this
"f6lMINEblHEROES 7[1.7-1.14+] b20% OFF SALE elPRISON SERVER RESET f- 9lVIP OUT NOW!"
It did get a lot of the jibberish out, but now there are random letters. These random letters are right after the § symbol. So I need to str_replace that symbol, as well as 1 character after that.
For your question you can try this:
$server->name = preg_replace('/§./', "", $server->name);
This will remove "§" with additional character as you ask.
But you might have to better understand "§" values and find custom solution.
You can explode the string by §, then implode them from index 1. Demo
$arr = explode("§",$str);
$result = array_reduce($arr,function($a,$b){return $a . substr($b,1);},"");

Retrieve 0 or more matches from comma separated list inside parenthesis using regex

I am trying to retrieve matches from a comma separated list that is located inside parenthesis using regular expression. (I also retrieve the version number in the first capture group, though that's not important to this question)
What's worth noting is that the expression should ideally handle all possible cases, where the list could be empty or could have more than 3 entries = 0 or more matches in the second capture group.
The expression I have right now looks like this:
SomeText\/(.*)\s\(((,\s)?([\w\s\.]+))*\)
The string I am testing this on looks like this:
SomeText/1.0.4 (debug, OS X 10.11.2, Macbook Pro Retina)
Result of this is:
1. [6-11] `1.0.4`
2. [32-52] `, Macbook Pro Retina`
3. [32-34] `, `
4. [34-52] `Macbook Pro Retina`
The desired result would look like this:
1. [6-11] `1.0.4`
2. [32-52] `debug`
3. [32-34] `OS X 10.11.2`
4. [34-52] `Macbook Pro Retina`
According to the image above (as far as I can see), the expression should work on the test string. What is the cause of the weird results and how could I improve the expression?
I know there are other ways of solving this problem, but I would like to use a single regular expression if possible. Please don't suggest other options.
When dealing with a varying number of groups, regex ain't the best. Solve it in two steps.
First, break down the statement using a simple regex:
SomeText\/([\d.]*) \(([^)]*)\)
1. [9-14] `1.0.4`
2. [16-55] `debug, OS X 10.11.2, Macbook Pro Retina`
Then just explode the second result by ',' to get your groups.
Probably the \G anchor works best here for binding the match to an entry point. This regex is designed for input that is always similar to the sample that is provided in your question.
(?<=SomeText\/|\G(?!^))[(,]? *\K[^,)(]+
(?<=SomeText\/|\G) the lookbehind is the part where matches should be glued to
\G matches where the previous match ended (?!^) but don't match start
[(,]? *\ matches optional opening parenthesis or comma followed by any amount of space
\K resets beginning of the reported match
[^,)(]+ matches the wanted characters, that are none of ( ) ,
Demo at regex101 (grab matches of $0)
Another idea with use of capture groups.
SomeText\/([^(]*)\(|\G(?!^),? *([^,)]+)
This one without lookbehind is a bit more accurate (it also requires the opening parenthesis), of better performance (needs fewer steps) and probably easier to understand and maintain.
SomeText\/([^(]*)\( the entry anchor and version is captured here to $1
|\G(?!^),? *([^,)]+) or glued to previous match: capture to $2 one or more characters, that are not , ) preceded by optional space or comma.
Another demo at regex101
Actually, stribizhev was close:
(?:SomeText\/([^() ]*)\s*\(|(?!^)\G),?\s*([^(),]+)(?=[^()]*\))
Just had to make that one class expect at least one match
(?:SomeText\/([0-9.]+)\s*\(|(?!^)\G),?\s*([^(),]+)(?=[^()]*\)) is a little more clear as long as the version number is always numbers and periods.
I wanted to come up with something more elegant than this (though this does actually work):
SomeText\/(.*)\s\(([^\,]+)?\,?\s?([^\,]+)?\,?\s?([^\,]+)?\,?\s?([^\,]+)?\,?\s?([^\,]+)?\,?\s?([^\,]+)?\,?\s?\)
Obviously, the
([^\,]+)?\,?\s?
is repeated 6 times.
(It can be repeated any number of times and it will work for any number of comma-separated items equal to or below that number of times).
I tried to shorten the long, repetitive list of ([^\,]+)?\,?\s? above to
(?:([^\,]+)\,?\s?)*
but it doesn't work and my knowledge of regex is not currently good enough to say why not.
This should solve your problem. Use the code you already have and add something like this. It will determine where commas are in your string and delete them.
Use trim() to delete white spaces at the start or the end.
$a = strpos($line, ",");
$line = trim(substr($line, 55-$a));
I hope, this helps you!

php preg_replace remove thousand separator in a string

there have a long articles, I want only remove thousand separator, not a comma.
$str = "Last month's income is 1,022 yuan, not too bad.";
//=>Last month's income is 1022 yuan, not too bad.
preg_replace('#(\d)\,(\d)#i','???',$str);
How to write the regex patterns? Thanks
If the simplified rule "Match any comma that lies directly between digits" is good enough for you, then
preg_replace('/(?<=\d),(?=\d)/','',$str);
should do.
You could improve it by making sure that exactly three digits follow:
preg_replace('/(?<=\d),(?=\d{3}\b)/','',$str);
If you have a look at the preg_replace documentation you can see that you can write captures back in the replacement string using $n:
preg_replace('#(\d),(\d)#','$1$2',$str);
Note that there is no need to escape the comma, or to use i (as there are not letters in the pattern).
An alternative (and probably more efficient) way is to use lookarounds. These are not included in the match, so they don't have to written back:
preg_replace('#(?<=\d),(?=\d)#','',$str);
The first (\d) is represented by $1, the second (\d) by $2. Therefore the solution is to use something like this:
preg_replace('#(\d)\,(\d)#','$1$2',$str);
Actually it would be better to have 3 numbers behind the comma to avoid causing havoc in lists of numbers:
preg_replace('#(\d)\,(\d{3})#','$1$2',$str);

Format for preg_replace to strip leading "1" and unwanted characters in phone number?

In my PHP code I am able to strip hyphens and parenthesis from phone numbers by using
preg_replace('/\D+/', "", $cell);
OR
preg_replace('/[ )(.-]/', "", $cell);
Two questions:
(1) Which of the above formats is best for removing ALL unwanted characters (,-,.,etc, as well as alpha characters.
(2) I also need to remove the leading "1" (country code for USA) if entered by user
There are many ways to remove non-digits, but I would suggest using whatever method make the most sense to you, that is, which one seems most intuitive and easy to understand when you look at the code again months from now.
Your \D works just fine but adding ^1 will also replace the leading 1 you're looking for.
preg_replace('/^1|\D/', "", $cell);
I would take a whitelist-approach instead: Remove everything, that is not a number, instead of removing everything, that is in the list a,
/[^0-9]/
your first expression \D should do the same. Any problems with that? If it works, keep it, because with the second (blacklist) approach you definitely miss characters. Either that, or your list must grow quite big.
Not a real answer, but definitely worth to mention: a country code is either +X, or 00X (+ is in fact just a shortcut for 00), thus removing a leading 1 may lead to quite ugly unwanted behaviour. Must say, that I don't know exactly, how it works over there, but in germany a local phone number can start with (theoretical) any number (except 0 of course). This said you should take care to replace a leading + with 00 before removing unwanted characters (1).
$cell=preg_replace("/[^0-9]/","", $cell);
$cell=preg_replace("/^1/","", $cell);
Would Do it

Making the money value with only numbers

I just posted this question link text about 5 minutes ago and I forgot to mention that the format was like this
"$2,090.99 "
I need the final value like
"209099"
Striping the final extra space and getting rid of any other punctuation in the money value with php so i can store into a mysql decimal 10,2
You can use a regular expression to replace everything that is not a digit:
$output = preg_replace('/\D/', '', $str);
\D is equivalent to [^\d] that is equivalent to [^0-9].
You might be better off using PHP 5.3's MessageFormatter, Locale and Intl classes if you'll be handling different locales and currency formats. The msgfmt_parse() method might just be what you need.

Categories