Reputation: 22760
I have seen a host of questions very similar to this but they're not able to quite collect what I'm looking for.
I have a search system for finding PDO named placeholders in an SQL string.
PDO placeholders can be A-z
, 0-9
, or _
and always begin with :
. However, in some circumstances date and time values also appear which naturally use :
(12:35
).
I need to check to find placeholders that match the PDO criteria but which are not just numeric.
Can I do this in a single Regex?
The regex I have developed at the moment is:
/:(?:[A-Z_]*)(?=[0-9]*)/gmi
But this cuts off when any digit is found, see the below example SQL:
SELECT name, horse, id, DATE_FORMAT(Nee.datetimed, '12:12:12 @ %D') as del_time
FROM members WHERE biztype LIKE CONCAT('%',:bizb,'%')
AND (locate LIKE '%hos%' OR locate LIKE '%all%')
AND bizcat LIKE CONCAT('%',:catb7,'%') ORDER BY `status` DESC, RAND()
I need to catch :catb7
and :bizb
but ignore the time values.
My Regex above catches :bizb
and catb
but that catch is incorrect as it chops off the 7.
/:(?:[A-Z_]*(?:[0-9]*))/gmi
Catches :12
and :12
which is incorrect.
/:(?:[A-Z_]*)(?=[0-9]*)/gmi
Catches :
as well which is incorrect.
Various tweaks and changes to the capture groups can't seem to find the correct result: Looking for:
:<any letter or number or underscore, any length, must contain at least one letter or underscore>
Valid catches:
:adbcd :5fedg :56_gt :der :9_6
INVALID catches:
:12 :1 :%D [MySQL date formatting]
Upvotes: 2
Views: 80
Reputation: 626952
You can use
\B:(?!\d+\b)\w+
See the regex demo.
Details:
\B
- a non-word boundary position (start of string or a non-word char must appear immediately to the left of the current location):
- a colon(?!\d+\b)
- a negative lookahead that fails the match if there are one or more digits followed with a word boundary immediately to the right of the current location\w+
- one or more word chars (letters/digit/underscores)Upvotes: 2