Although it is possible to make a regex - https://www.rexegg.com/regex-best-trick.html#simplecase - involving https://www.regular-expressions.info/lookaround.html , I find it easier to use a small "truck" that uses https://www.regular-expressions.info/brackets.html .Basically, if you have a string like this:$texto = "123 abc '456' def789'112' ghi";
From what I understand, you just want to capture 123 and 789, because it is the numbers that are not among simple quotes ('). So you could have such an expression:preg_match_all("/\'\\d+\'|(\\d+)/", $texto, $matches);
This regex uses https://www.regular-expressions.info/alternation.html (|) to say you want something or another. These things are:number among simple quotes: '\d+', ornumber (without quotation marks) and within brackets, to form a catch group: (\d+)Remembering that some regex characters are duly escaped with \ because they within a string.With that, one match of regex can fall into one of the 2 cases:if the number is between simple quotes, it falls in the first stretchotherwise, falls in the second stretchIf it falls in the first case, the catch group is not filled, and if it falls in the second stretch, the catch group is filled.Therefore, to pick up the numbers that are not among simple quotes, just check if the catch group is filled. And so that the array returns in a format easier to check this, we can use the option PREG_SET_ORDER:$texto = "123 abc '456' def789'112' ghi";
preg_match_all("/\'\\d+\'|(\\d+)/", $texto, $matches, PREG_SET_ORDER, 0);
var_dump($matches);
This code produces the following output:array(4) {
[0]=>
array(2) {
[0]=>
string(3) "123"
[1]=>
string(3) "123"
}
[1]=>
array(1) {
[0]=>
string(5) "'456'"
}
[2]=>
array(2) {
[0]=>
string(3) "789"
[1]=>
string(3) "789"
}
[3]=>
array(1) {
[0]=>
string(5) "'112'"
}
}
Notice that, matches that fall in the second case (number is not between single quotes), the array has 2 positions. The first corresponds to the whole match, and the second corresponds to the catch group (in this case they are equal, but depending on the expression, may not be).In cases where the number is in quotation marks, the respective array only has a position, since in these cases the catch group is not filled.Then just go through the array matches and check which of the internal arrays has the sealed capture group (i.e., just see if the size is greater than 1):foreach ($matches as $m) {
if (count($m) > 1) { // grupo de captura preenchido (número não está entre aspas)
echo $m[1]. "\n";
}
}
The exit of this foreach is:123
789
If you want numbers with decimal places, just change \d+ by \d+\.\d+ (that inside the string would be \\d+\\.\\d+) or any other expression you are using to capture the numbers.If the houses after comma are optional, for example, you can use \d+(?:\.\d+)?. It is not the specific focus of the question, but number validation can become complicated, https://stackoverflow.com/a/4247184 .As remembered by https://pt.stackoverflow.com/users/6333/fernandosavio in https://pt.stackoverflow.com/questions/352142/usando-regex-em-php-para-capturar-qualquer-n%C3%BAmero-que-n%C3%A3o-esteja-dentro-de-aspas/352150?noredirect=1#comment706656_352150 , it is possible to delimit the string with simple quotes also, so the \ no need to be written as \\:preg_match_all('/\'\d+\'|(\d+)/', $texto, $matches, PREG_SET_ORDER, 0);
See https://ideone.com/jb4Yph an example.This "truck" was based https://www.rexegg.com/regex-best-trick.html#notarzan .