Find a Percentage Value in a String Using Preg_Match

Find a percentage value in a string using preg_match

if (preg_match("/[0-9]+%/", $string, $matches)) {
$percentage = $matches[0];
echo $percentage;
}

PHP - Find percentage value from string

You arent' looking for the . character in your regex. Try this one:

if (preg_match("/[0-9]+\.[0-9]+%/", $crimeexe, $matches)) {
$crimeexe = $matches[0];
}

Extract percentage from a string in PHP

Try matching \d+(?:\.\d+)?%, which makes the decimal component of the percentage optional:

$string = "This is a text with decimal value 10.1% and non decimal value 5%.";
preg_match_all("/\d+(?:\.\d+)?%/", $string, $matches);
print_r($matches[0]);

This prints:

Array
(
[0] => 10.1%
[1] => 5%
)

Get number before the percent sign

Update:

From the code you added to your question, I get the impression your percentages might look like 12.3% or even .50%. In which case, the regex you're looking for is this:

if (preg_match_all('/(\d+|\d+[.,]\d{1,2})(?=\s*%)/','some .50% and 5% text with 12.5% random percentages and 123 digits',$matches))
{
print_r($matches);
}

Which returns:

Array
(
[0] => Array
(
[0] => .50
[1] => 5
[2] => 12.5
)

[1] => Array
(
[0] => .50
[1] => 5
[2] => 12.5
)

)

the expression explained:

  • (\d+|\d*[.,]\d{1,2}): is an OR -> either match digits \d+, or \d* zero or more digits, followed by a decimal separator ([.,]) and 1 or 2 digits (\d{1,2})
  • (?=\s*%): only if the afore mentioned group is followed by zero or more spaces and a % sign

Using a regular expression, with a positive lookahead, you can get exactly what you want:

if (preg_match_all('/\d+(?=%)/', 'Save 20% if you buy 5 iPhone charches (excluding 9% tax)', $matches))
{
print_r($matches[0]);
}

gives you:

array (
0 => '20',
1 => '9'
)

Which is, I believe, what you are looking for

The regex works like this:

  • \d+ matches at least 1 digit (as many as possible)
  • (?=%): provided they are followed by a % sign

Because of the lookahead, the 5 isn't matched in the example I gave, because it's followed by a space, not a % sign.

If your string might be malformed (have any number of spaces between the digit and the % sign) a lookahead can deal with that, too. As ridgerunner pointed out to me, only lookbehinds need to be of fixed size, so:

preg_match_all('/\d+(?=\s*%)/', $txt, $matches)

The lookahead works like this

  • \s*: matches zero or more whitespace chars
  • %: and percent sign

Hence, both 123 % and 123% fit the pattern, and will match.

A good place to read up on regex's is regular-expressions.info


If "complex" regex's (ie with lookaround assertions) aren't your cup of tea (yet, though I strongly suggest learning to use them), you could resort to splitting the string:

$parts = array_map('trim', explode('%', $string));
$percentages = array();
foreach($parts as $part)
{
if (preg_match('/\d+$/', $part, $match))
{//if is required, because the last element of $parts might not end with a number
$percentages[] = $match[0];
}
}

Here, I simply use the % as delimiter, to create an array, and trim each string section (to avoid trailing whitespace), and then procede to check each substring, and match any number that is on the end of that substring:

'get 15% discount'
['get 15', 'discount']
/\d+$/, 'get 15' = [15]

But that's just an awful lot of work, using a lookahead is just way easier.

PHP - Find percentage value from string

You arent' looking for the . character in your regex. Try this one:

if (preg_match("/[0-9]+\.[0-9]+%/", $crimeexe, $matches)) {
$crimeexe = $matches[0];
}

Regex to match string between %

Replace the "." in your regular expression with "[^%]":

preg_match_all("/%[^%]*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);

What is happening is that the "." is "greedily" matching as much as it possibly can, including everything up-to the final % on the line. Replacing it with the negated character class "[^%]" means that it will instead match anything except a percent, which will make it match just the bits that you want.

Another option would be to place a "?" after the dot, which tells it "don't be greedy":

preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);

In the above example, either option will work, however there are times when you may be searching for something larger than a single character, so a negated character class will not help, so the solution is to un-greedify the match.

Get The Full Word Containing % In String

Try this:

$re = '(\d+(\.\d+)?%)'; 
$str = "Get 20% Off== FG";
preg_match_all($re, $str, $matches);
print_r($matches[0]);

Output:

Array ( [0] => 20% )

preg_match replace entire line

You can match all lines that do not start with # until you can match # at the start.

^(?:(?!#).*\R)+#
  • ^ Start of string
  • (?: Non capture group
    • (?!#).*\R Negative lookahead, assert not # directly at the right. If that is the case, match the whole line followed by a newline
  • )+ Close group and repeat 1+ times to match at least a single line
  • # Match literally to make sure that the character is present

Regex demo

In the replacement use a #

Example

$re = '/^(?:(?!#).*\R)+#/m';
$str = 'text1
text2
text3
text3
# text 5';

echo preg_replace($re, "#", $str);

Output

# text 5


Related Topics



Leave a reply



Submit