Prevent the number of characters over 20 to pass the validation - php

I have this light regular expression to validate the coordinates: ^([0-9.,-]+){18,20}$^. If the coordinates for example is 33.431441,-170.15625 and are under 18 characters, I'll get an error message. Good! But if I add more characters to say 23 or more it will pass even if I have set an lock to 20.
You can test the regexp on http://regexpal.com/.
How can I fix this problem?
Thanks in advance.

You need the leading carat, or you are only checking the last 18-20 characters in the string:
/^[0-9\.,-]{18,20}$/
Edit: also, drop the plus sign, as others have noted.
Edit2: Parens are superfluous
Edit3: need to escape the period (otherwise, it matches any character)

It should be just ^([0-9.,-]){18,20}$. The + means one or more of the preceding elements, and then you have 18 to 20 of those. You want just 18 to 20 of the preceding elements. You don't need the caret at the end as that means "beginning of string"

Here's a suggestion if you want to constrain the limits and validate the coordinate format.
Assuming Lat,Long:
^-?\d{1,2}(\.\d{1,5})?,-?\d{1,3}(\.\d{1,5})?$
The comma will always consume 1 characters.
Max longitude primary digits are 3 characters.
Max latitude primary digits are 2 characters.
Optional decimal points take up 2 characters.
Optional polarity is 2 characters.
This leaves us with 10 characters reserved, giving us 5 left over on each side for decimal places. You can adjust \d{1,5} to something like \d{4,5} and enforce the decimal places if you require a minimum of 18.

Related

Representing alphanumeric string as a shortest possible numeric string

I'm looking for a way to convert an alphanumeric string, e.g. "aBcd3f", into a purely numeric representation, and get the shortest possible input string. The valid characters in the input string are a-z, A-Z, 0-9, and the resultant string would be comprised only of digits 0-9.
Since there are 62 valid values for each character in the input string, I can assign values 00-61 to each input character, and covert the 6 input characters into a 12 character numeric string.
But I would like to get something more compact, if possible - e.g. 8-10 digits. Is it possible, and if so, are there any algorithms or functions for doing this in PHP?
Note that this has to be a 2-way function. I also need to be able to go back from the numeric string to the alphanumeric.
I haven't found this question asked on this site. My question is the opposite of this question, as I'm trying to go in the opposite direction.
A decimal digit encodes log2(10) = 3.32 bits of information on average. Alphanumeric data has 62 possible "digits", so each one encodes log2(62) = 5.95 bits of information on average.
This means that converting from alphanumeric to decimal digits only will require approximately 5.95 / 3.32 = 1.79 times more characters in the output than there are in the input. If your output is constrained to 10 characters maximum you can expect it to encode at most 5.58 characters of alphanumeric input, which for practical purposes means just 5. There is no room for maneuvering here; this is cold math.
The manner of converting from one representation to the other is fairly straightforward, because in essence you are simply converting a number from base 62 to base 10 and back. You can tweak the code from this answer of mine only slightly to achieve the aim.
See it in action.
Note that with the (arbitrary) order of digits I picked the "largest" possible input with 5 characters is "ZZZZZ", which encodes to 9 decimal digits. If you expand the input to 6 characters the largest input would be "ZZZZZZ" which would need 11 decimal digits to encode -- more than the limit we imposed, as predicted.
Also note that this analysis assumes every possible input string is as likely to occur as any other, i.e. the input is perfectly random. If this is not the case then the actual information content of the input would be lower than the theoretical maximum and consequently you could take advantage of this with some kind of compression scheme.

Using regex/preg_match() to check if a set of coordinates in decimal degrees is valid

I've learnt a bit of basic regex to wet my feet, but it's all still a bit too complicated for me. I need to take a set of user-inputted coordinates in decimal degrees (example):
$latitude = -42.323432
$longitude = 176.232123
and check whether they're valid using the preg_match() function in PHP. Seems simple, but I can't write the regular expression for the life of me that would ensure that no bad data gets through. I'll check the northing and easting separate of each other so this preg_match() will be iterated through twice using a foreach loop.
I think I've figured out all the necessary conditions:
The first character can either be a minus, a plus, or a number. The minuses and pluses are optional.
The total count of numbers before the decimal point can be 1 to 3, but not 0 or above 3.
Therefore there must be a decimal point in either the second place, or the fourth place. (2.2332, -123.422)
There must be at EXACTLY one decimal point in the whole string, there can be 0 OR 1 minuses or pluses in the whole string.
I want at least 3 decimal places of precision AFTER the decimal point. There is no maximum limit (I'll simply round it to 6 dp myself)
If there are any characters besides numbers, a decimal point, and an optional plus and minus, reject it.
After this though, I'm stuck! Any help would be appreciated in writing the regex expression. Thanks...
Let's take a stab at it:
/^[+\-]?[0-9]{1,3}\.[0-9]{3,}\z/
Broken down:
^ - start of string
[+\-]? - zero or one from set of `+` and `-`
[0-9]{1,3} - 1 to 3 digits
\. - decimal point
[0-9]{3,} - 3 or more digits
\z - end of string
(note, this is untested ;))

Sha 1 php, possible variations and regex

First,
Is it possible for a sha1 hash to be all numbers or letters,
And second is there any need for the start and end delimiters when using a regex to check for a sha 1 hash, ie,
/^[0-9a-f]{40}$/i
inplace of
/[0-9a-f]{40}/i
Is there any need to use the delimeters?
I ask as should I check if the pattern has at least one number and at least one letter, or does this not matter?
A sha1 hash is a 160 bit value that can be between all 0s and all 1s. This means that yes, in theory it can be all numbers or all letters (more specifically, the hex representation of it can be).
As for the beginning and ending markers, they are required unless you check the string in other ways. The two patterns you posted are not equivalent:
/^[0-9a-f]{40}$/i
A string that consists of and only of 40 character in 0-9 or a-f.
/[0-9a-f]{40}/i
A string that contains 40 character in 0-9 or a-f in a row.
In other words, the first pattern would consider this invalid whereas the second would not:
|0000000000000000000000000000000000000000|
The second pattern would match the 40 valid characters in the middle and not care about the rest of it.
You could effectively turn the second pattern into the first if you also used strlen to verify that the string is exactly 40 characters. This would be a bit redundant though, as you'd essentially then have a pattern of:
A string that: (contains 40 characters in 0-9 or a-f in a row) and (is exactly 40 characters).
The first version expresses it more compactly, though the second is a bit more obvious.

How can I use regex to solve this?

I have two strings that I need to pull data out of but can't seem to get it working. I wish I knew regular expression but unfortunately I don't. I have read some beginner tutorials but I can't seem to find an expression that will do what I need.
Out of this first string delimited by the equal character, I need to skip the first 6 characters and grab the following 9 characters. After the equal character, I need to grab the first 4 characters which is a day and year. Lastly for this string, I need the remaining numbers which is a date in YYYYmmdd.
636014034657089=130719889904
The second string seems a little more difficult because the spaces between the characters differ but always seem to be delimited by at minimum, a single space. Sometimes, there are as many as 15 or 20 spaces separating the blocks of data.
Here are two different samples that show the space difference.
!!92519 C 01 M600200BLNBRN D55420090205M1O
!!95815 A M511195BRNBRN D62520070906 ":%/]Q2#0*&
The data that I need out of these last two strings are:
The zip code following the 2 exclamation marks.
The single letter 'M' following that. It always appears to be in a 13 character block
The 3 numbers after the single letter
The next 3 numbers which are the person's height
The following next 3 are the person's weight
The next 3 are eye color
The next block of 3 which are the person's hair color
The last block that I need data from:
I need to get the single letter which in the example appears to be a 'D'.
Skip the next 3 numbers
The last and remaining 8 numbers which is a date in YYYYmmdd
If someone could help me resolve this, I'd be very grateful.
For the first string you can use this regular expression:
^[0-9]{6}([0-9]{9})=([0-9]{4})([0-9]{4})([0-9]{2})([0-9]{2})$
Explanation:
^ Start of string/line
[0-9]{6} Match the first 6 digits
([0-9]{9}) Capture the next 9 digits
= Match an equals sign
([0-9]{4}) Capture the "day and year" (what format is this in?)
([0-9]{4}) Capture the year
([0-9]{2}) Capture the month
([0-9]{2}) Capture the date
$ End of string/line
For the second:
^!!([0-9]{5}) +.*? +M([0-9]{3})([0-9]{3})([A-Z]{3})([A-Z]{3}) +([A-Z])[0-9]{3}([0-9]{4})([0-9]{2})([0-9]{2})
Rubular
It works in a similar way to the first. You may need to adjust it slightly if your data is not exactly in the format that the regular expression expects. You might want to replace the .*? with something more precise but I'm not sure what because you haven't described the format of the parts you are not interested in.

Regular expression to match letters, numbers, and certain symbols

I need to validate a username in PHP. It can be:
Letters (upper and lower case)
Numbers
Any of these symbols :.,?!#
Up to 15 characters OR 16 if the last character is one of the following #$^ (it can also be 15 or less with one of these 3 characters at the end only)
How do I do this?
Start with this:
/^[a-zA-Z0-9:.,?!#]{3,15}[#$^]?$/
then refine it to your needs. Try to see if you need escaping of the special char, but you should get the idea.
This means: from a to z, from A to Z, from 0 to 9 and :.,?!# repeated from 3 to 15 times, optionally followed by one among #$^

Categories