Can someone help me with this bug. I need the following code to NOT match if there is another number afterwards
$query = "SELECT * FROM mytable WHERE server_name REGEXP '(server ?" . $server_id . ")' ";
For example, if $server_id is 50, it currently matches server 500, 501 etc and I dont want it too, but it should be allowed to match 'server50' 'server50 100mbit' 'server50,100mbit' etc. the character afterwards needs to be anything other than another number and can even be nothing at all.
Stu
Matching a non-digit is [^0-9] in regular expressions.
$query = "SELECT * FROM mytable
WHERE server_name REGEXP 'server ?" . $server_id . "([^0-9]|\$)' ";
You will want to do a regex against a number. /^0-9/ and what you would then need to do is to if returns a match, you need to say "Hey now, thats a number, wrong!" whereas if it returns an empty set, it would be a match.
You can also do a regex against it NOT being a number, where as you put the NOT character inbetween the ^ and the [.
I forget NOT syntaqx off the top of my head at the moment, but in common lingo, it would look like
/^![0-9]/
the slashes are usually the sign of a regex.
with your stuff, you need to do something like /^serverid[0-9][0-9]/ which will compare the regex with SERVERID[][] so it will only read the first 2 characters. If there are MORE characers, you can boot it out, or things like that
Related
How can I get, into an array, all occurrences of this pattern 4321[5-9][7-9]{6} but excluding, for example, the occurrences where there is a digit immediately before the value, or immediately after it?
For instance, 43217999999 should be valid but 143217999999 (note the number 1 at the beginning) should not be valid.
As the first example, 432179999991 shouldn't be valid because of the 1 that it has in the end.
The added difficulty, at least for me, is that I have to parse this in whatever position I can find it inside a string.
The string looks like this, literally:
43217999997 / 543217999999 // 43217999998 _ 43217999999a43216999999-43216999999 arandomword 432159999997
As you would be able to note, it has no standard way of separating the values (I marked in bold the values that would make it invalid, so I shouldn't match those)
My idea right now is something like this:
(\D+|^)(4321[5-9][7-9]{6})(\D+|$)
(\D+|^) meaning that I expect in that position the start of the string or at least one non-digit and (\D+|$) meaning that I expect there the end of the string or at least one non-digit.
That obviously doesn't do what I picture in my head.
I also tried do it in two steps, first:
preg_match_all("/\D+4321[5-9][7-9]{6}\D+|4321[5-9][7-9]{6}\D+|4321[5-9][7-9]{6}$/", $input, $outputArray);
and then:
for($cont = 0; $cont < count($outputArray); $cont++) {
preg_match("/4321[5-9][7-9]{6}/", $outputArray[0][$cont], $outputArray2[]);
}
so I can print
echo "<pre>" . print_r($outputArray2, true) . "</pre>";
but that doesn't let me exclude the ones that have a number before the start of the value (5432157999999 for example), and then, I am not making any progress with my idea.
Thanks in advance for any help.
If you literally want to check if there is no digit before or after the match you can use negative look ahead and look behind.
(?![0-9]) at the end means: "is not followed by 0-9"
(?<![0-9]) at the start means: "is not preceded by 0-9"
See this example https://regex101.com/r/6xbmJk/1
I am using the following regex:
^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?\$
I use this regex to check for valid prices -- so it catches/rejects things like xxx, or llddd or 34.23dsds
and allows things like 100 or 120.00
The problem with it seems to be if it is blank(empty) it passes as valid which it should not -- any ideas how to change this??
Thanks
One of your problems is that you use the dot in your regex which stands for "any character". If you mean a dot you need to escape it like this \.
Also you should have at least one number in it so exchange the asterisk * by a + for "one or more".
Then you can have .,.,.,.,.,.,- if you do not remove the comma and dot from the first part:
^[0-9]+(([\.,][-])|([\.,][0-9]{2}))?$
Taking yoiur regex and just solving the "don't match blanks" problem:
^[0-9.,]+(([.,][-])|([.,][0-9]{2}))?$
the * allows 0 or more, while the + allows 1 or more, thus the * allowed blanks but the + will not, instead there must be at least one digit.
EDIT:
You should clean this regex up a bit to be
^[0-9]+(?:[.,-](?:[0-9]{2})?)?$
This solves the matching of ",,,"
http://www.regextester.com/?fam=95185
EDIT 2: #Fuzzzzel pointed out that this did not match the case "50,-" which we assume you would like to match and that removing capturing groups is presumptive. Here's the latest iteration of my suggested regex:
^[0-9]+([.,-](-|([0-9]{2}))?)?$
I'm trying to use regex to parse a string like the below:
/subject=hello±#text=something that may contain\#hello.com or a normal sla/sh±#date=blah/somethingelseI don't want to capture after the first/
into:
subject = hello
text =something that may contain\#hello.com or a normal sla/sh
date = blah
Ideally I'd like to be able to split the string after the first '/' by something like '±#' - and only that combination in that order.
I've looked around and at the minute have the below:
([^/±#,= ]+)=([^±#,= ]+)
But this doesn't match only '±#' - it matches either # or ±.
It also doesn't cope with the escaped #. (Instead i get: text= something that may contain\ ).
Is there a better way to do this?
Thanks
Try this:
(?:\/|(?<=±#))(.*?=.*?)(?:±#|$|\/(?!.*±#))
See live demo
An important part is the negative look ahead after the trailing slash /(?!.*±#) - this means "match a slash, but only if ±# doesn't appear in the input after it".
Given this input:
/subject=hello±#text=something that may contain\#hello.com or a normal sla/sh±#date=blah/somethingelseI don't want to capture after the first/
It produces matches whose group 1 are:
subject=hello
text=something that may contain\#hello.com or a normal sla/sh
date=blah
I got this pattern(I am using php):
'/\[link\=((https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?)\]/i'
When i search for this string: http://phpquest.zapto.org/users/register.php
The matches are(The order is 0-5):
'[link=http://phpquest.zapto.org/users/register.php]'
'http://phpquest.zapto.org/users/register.php'
'http://'
'phpquest.zapto'
org
''
When i replace the * with + inside the last subpattern like that:
'/\[link\=((https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]+)*\/?)\]/i'
The matches are(The order is 0-5):
'[link=http://phpquest.zapto.org/users/register.php]'
'http://phpquest.zapto.org/users/register.php'
'http://'
'phpquest.zapto'
org
'/users/register.php'
If anyone can help me understand why is that i will be very thankful, Thank you all and have a nice day.
Maybe a simpler example is when you compare this to this.
The regexes involved are:
(a*)*
and
(a+)*
And the test string is aaaaaa.
What happens is that after capturing the main group (in the example I provided, the series of a's) it attempts to match more, but cannot. But wait! It can also match nothing, because * means 0 or more times!
Therefore, after matching all the a's, it will match and catch a 'nothing' and since only the last captured part is stored, you get '' as result of the capture group.
In (a+)*, after matching and catching aaaaaa, it cannot match or catch anything more (+ prevents it to match nothing, as opposed to *) and hence, aaaaaa is the last match.
This can be simplified with the following pattern.
/\[link=(https?:\/\/)(([a-z0-9]+\.?)+)((\/[^\/]+)+)\/?\]/i
The regex symbol * is not greedy, while + is. Hence, when using the + in the second attempt, all path components are matched and that group is captured; however, in the first attempt with *, since you were only capturing the inner * group with parenthesis, you matched the un-greedy sample of the *, in this case nothing.
I think I'm going crazy with this...
I've tried a lot of combinations and I can't get with the good one.
I need to find all the SQL queries in a PHP code after having read it with a file_get_contents().
Of course, all those queries are variable assignations like:
$sql1 = "
SELECT *
FROM users u
WHERE u.name LIKE '%".$name."%' AND ... ;
";
or
$sql2 = "
SELECT *
FROM users u
WHERE u.id = ".$user_id;
or
$sql3 = '
SELECT *
FROM users u
ORDER BY u.surname1 DESC
'; //this query blablabla.......
So you can see that there are many factors to take in account for PHP variables.
First I've tried with an approximation based on getting the variable itself combined with the getting it's content...
I've tried to find specific words from SQL in a regex pattern too...
Whatever...
I don't know how to do it.
Getting all the variable and it's assignation, grouping the assignation and after it, looping through matches searching for special SQL words (that's what I've right now, but it doesn't work cause assignation regex part).
Directly searching for a SQL queries with a good regex?
PHP variables (specifically strings), contains partially concatenations with other variables, double and single quoted strings, comments at the end of ";" or in the middle...
So what can I do?
So far, that's my variable regex part:
$regex_variable = '\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*[\+\-\*\/\%\.\&\|\^\<\>]*=\s*';
Which I concatenate with $regex_sql which I've tried different forms:
//$regex_sql = '(["\'])(.*?)\2\s*;';
//$regex_sql = '(["\'])([^;]*?)\2\s*;';
//$regex_sql = '(?<!")\b\w+\b|(?<=")\b[^"]+';
//$regex_sql = '([^;]+)(?<=["\']);(?!["\'])';
//$regex_sql = '(.*?;)[^\\$]*';
None of those correctly works.
Can you help me please? I'm sure the best approximation it's getting all the variable itself, and after it, testing the assignation for containing some special SQL words like SELECT, WHERE, UNION, ORDER, ...
So much thanks in advance!
Mark.
edit:
To add that of course, variables with queries could have any kind of form. Those from above are just simple examples.
We're talking about things such:
$s = 'insert into tabletest(a,b,c) values('asd','r32r32','fdfdf')';
or
$where = 'where a=2';
$sql="select distinct * from test ".$where;
or
$a = '
select *
from users
left outer join ...
inner join ...
left join ...
where ...
group by ...
having ...
order by ...
limit ...
...
';
or
...
Imagine a lot of programmers, creating queries inside the code, anyone doing it at their own way... :\
I've to get ALL of them. At least, maximise the results... ^^'
I suggest you take a look at the PHP Tokenizer - you can use it to tokenize your source (i.e. parse it so it is easier to comprehend) then you can look through the tokens for strings and variables that match your requirements, knowing that each token ; ends a line of code.
Don't know if this is what you are looking for :
preg_match_all('/\$.*?=(.*?)(?<=[\'"]);/s', $subject, $result, PREG_PATTERN_ORDER);
$result = $result[1];
This will have all the assignments(assignations) stored in $result. I tested it with all your samples.
Sorry if you wanted something else.
Explanation :
"
\$ # Match the character “\$” literally
. # Match any single character
*? # Between zero and unlimited times, as few times as possible, expanding as needed (lazy)
= # Match the character “=” literally
( # Match the regular expression below and capture its match into backreference number 1
. # Match any single character
*? # Between zero and unlimited times, as few times as possible, expanding as needed (lazy)
)
(?<= # Assert that the regex below can be matched, with the match ending at this position (positive lookbehind)
['\"] # Match a single character present in the list “'\"”
)
; # Match the character “;” literally
"