Regular Expression for the Pattern? - regex

I'm required to write a regular expression that has the following rules:
Digits between 1 to 4
hyphen (only one and can occur at any position)
Length of Text must be less than or equal to 6 (including the potential hyphen)
May end with a letter or a number, but not a hyphen.
Some valid examples are:
1-3411
12-413
123-2A
11-1
These examples are invalid:
12--11 ( since it contains two hyphens)
1-2345 ( since it contains number 5)
11-2311 ( since length is more than 6)
The RegEx that I wrote is:
^[1-4]-[1-4]{4}|^[1-4]{2}-[1-4]{3}|^[1-4]{3}-[1-4]{2}|^[1-4]{4}-[1-4]
However, this does not seem to be working, and it doesn't handle the case of a single character being is present in the end.
Can some some please help me determine a way of handling this?
<>
is character occurs in last position then before character we must have a digit not hypen .
i.e 11-a ( must fail)
11-1a (must pass)

^(?!(?:[^-\n]*-){2})(?:[1-4-]{1,5}[1-4]|[1-4-]{1,5}[a-zA-Z])$
You can handle that using a lookahead.See demo.
https://regex101.com/r/tS1hW2/16

If you have such a complex requirement, it is always easy to use lookarrounds to form an and-pattern matching each condition at the same time. Sometimes you need to split up ONE condition into two:
Base-Match: 6 or less digits: ^.{1,6}$
(AND) Only 1-4 and hyphen and letter: ^[1-4a-z\-]+$ (not accurate, requires next line)
(AND) First 1...5 elements NO Letter: ^[1-4\-]{1,5}[1-4a-z]$
(AND) No double hypen and not at the end: ^[^-]*-[^-]+$
Putting all together leads to:
(?=^[1-4\-]{1,5}[1-4a-z]$)(?=^[^-]*-[^-]*$)(?=^[1-4a-z\-]+$)^.{1,6}$
Debuggex Demo

Related

Need regex expression with multiple conditions

I need regex with following conditions
It should accept maximum of 5 digits then upto 3 decimal places
it can be negative
it can be zero
it can be only numbers (max. upto 5 digit place)
it can be null
I have tried following but its not, its not fulfilling all conditions
#"^([\-\+]?)\d{0,5}(.[0-9]{1,3})?)$"
E.g. maximum value can hold is from -99999.999 to 99999.999
Use this regex:
^[-+]?\d{0,5}(\.[0-9]{1,3})?$
I only made two changes here. First, you don't need to escape any characters inside a character class normally, except for opening and closing brackets, or possibly backslash itself. Hence, we can use [-+] to capture an initial plus or minus. Second, you need to escape the dot in your regex, to tell the engine that you want to match a literal dot.
However, I would probably phrase this regex as follows:
^[-+]?\d{1,5}(\.[0-9]{1,3})?$
This will match one to five digits, followed by an optional decimal point, followed by one to three digits.
Note that we want to capture things like:
0.123
But not
.123
i.e. we don't want to capture a leading decimal point should it not be prefixed by at least one number.
Demo here:
Regex101
I assume you're doing this in C# given the notation. Here's a little code you can use to test your expression, with two corrections:
You have to escape the dot, otherwise it means "any character". So, \. instead of .
There was an extraneous close parenthesis that prevented the expression from compiling
C#:
var expr = #"^([\-\+]?)\d{0,5}(\.[0-9]{1,3})?$";
var re = new Regex(expr);
string[] samples = {
"",
"0",
"1.1",
"1.12",
"1.123",
"12.3",
"12.34",
"12.345",
"123.4",
"12345.123",
".1",
".1234"
};
foreach(var s in samples) {
Console.WriteLine("Testing [{0}]: {1}", s, re.IsMatch(s) ? "PASS" : "FAIL");
}
Results:
Testing []: PASS
Testing [0]: PASS
Testing [1.1]: PASS
Testing [1.12]: PASS
Testing [1.123]: PASS
Testing [12.3]: PASS
Testing [12.34]: PASS
Testing [12.345]: PASS
Testing [123.4]: PASS
Testing [12345.123]: PASS
Testing [.1]: PASS
Testing [.1234]: FAIL
It should accept maximum of 5 digits
[0-9]{1,5}
then upto 3 decimal places
[0-9]{1,5}(\.[0-9]{1,3})?
it can be negative
[-]?[0-9]{1,5}(\.[0-9]{1,3})?
it can be zero
Already covered.
it can be only numbers (max. upto 5 digit place)
Already covered. 'Up to 5 digit place' contradicts your first rule, which allows 5.3.
it can be null
Not covered. I strongly suggest you remove this requirement. Even if you mean 'empty', as I sincerely hope you do, you should detect that case separately and beforehand, as you will certainly have to handle it differently.
Your regular expression contains ^ and $. I don't know why. There is nothing about start of line or end of line in the rules you specified. It also allows a leading +, which again isn't specified in your rules.

Regular expression for password (at least 2 digits and one special character and minimum length 8)

I have been searching for regular expression which accepts at least two digits and one special character and minimum password length is 8. So far I have done the following: [0-9a-zA-Z!##$%0-9]*[!##$%0-9]+[0-9a-zA-Z!##$%0-9]*
Something like this should do the trick.
^(?=(.*\d){2})(?=.*[a-zA-Z])(?=.*[!##$%])[0-9a-zA-Z!##$%]{8,}
(?=(.*\d){2}) - uses lookahead (?=) and says the password must contain at least 2 digits
(?=.*[a-zA-Z]) - uses lookahead and says the password must contain an alpha
(?=.*[!##$%]) - uses lookahead and says the password must contain 1 or more special characters which are defined
[0-9a-zA-Z!##$%] - dictates the allowed characters
{8,} - says the password must be at least 8 characters long
It might need a little tweaking e.g. specifying exactly which special characters you need but it should do the trick.
There is no reason, whatsoever, to implement all rules in a single regex.
Consider doing it like thus:
Pattern[] pwdrules = new Pattern[] {
Pattern.compile("........"), // at least 8 chars
Pattern.compile("\d.*\d"), // 2 digits
Pattern.compile("[-!"ยง$%&/()=?+*~#'_:.,;]") // 1 special char
}
String password = ......;
boolean passed = true;
for (Pattern p : pwdrules) {
Matcher m = p.matcher(password);
if (m.find()) continue;
System.err.println("Rule " + p + " violated.");
passed = false;
}
if (passed) { .. ok case.. }
else { .. not ok case ... }
This has the added benefit that passwort rules can be added, removed or changed without effort. They can even reside in some ressource file.
In addition, it is just more readable.
Try this one:
^(?=.*\d{2,})(?=.*[$-/:-?{-~!"^_`\[\]]{1,})(?=.*\w).{8,}$
Here's how it works shortly:
(?=.*\d{2,}) this part saying except at least 2 digits
(?=.*[$-/:-?{-~!"^_[]]{1,})` these are special characters, at least 1
(?=.*\w) and rest are any letters (equals to [A-Za-z0-9_])
.{8,}$ this one says at least 8 characters including all previous rules.
Below is map for current regexp (made with help of Regexper)
UPD
Regexp should look like this ^(?=(.*\d){2,})(?=.*[$-\/:-?{-~!"^_'\[\]]{1,})(?=.*\w).{8,}$
Check out comments for more details.
Try this regex. It uses lookahead to verified there is a least two digits and one of the special character listed by you.
^(?=.*?[0-9].*?[0-9])(?=.*[!##$%])[0-9a-zA-Z!##$%0-9]{8,}$
EXPLANATION
^ #Match start of line.
(?=.*?[0-9].*?[0-9]) #Look ahead and see if you can find at least two digits. Expression will fail if not.
(?=.*[!##$%]) #Look ahead and see if you can find at least one of the character in bracket []. Expression will fail if not.
[0-9a-zA-Z!##$%0-9]{8,} #Match at least 8 of the characters inside bracket [] to be successful.
$ # Match end of line.
Regular expressions define a structure on the string you're trying to match. Unless you define a spatial structure on your regex (e.g. at least two digits followed by a special char, followed by ...) you cannot use a regex to validate your string.
Try this : ^.*(?=.{8,15})(?=.*\d)(?=.*\d)[a-zA-Z0-9!##$%]+$
Please read below link for making password regular expression policy:-
Regex expression for password rules

X-Path + RegEx matching pattern

Given the following,
<Line>
<Supplier>Fuel Surcharge - 36</Supplier>
<Supplier>Fuel Surcharge - 35</Supplier>
<Supplier>46081 46150 46250 46280 46286</Supplier>
<Supplier>Fuel Surcharge - 35451</Supplier>
<Supplier>46081</Supplier>
</Line>
The idea here is to return "true" when the node carries a number of 5 digits with iteration.
This is what I have done so far,
matches(./Supplier, "[^(\d{5}\s*)+]");
The regex here is to extract the value that has 5 digits with or without space regardless of the iteration.
The results I am getting is all true. Means its not right somewhere. Can you assist me with this.
Thanks.
There are two problems with your expression:
No semicolon in the end of an XPath expression (syntax error).
Your regex is messed up, it matches everything that does not contain anything out of the character class parentheses, digits, curly brackets, the digit 5, spaces, and the star and plus character.
fn:matches(xs:string?, xs:string) requires two strings as parameters, you're passing a sequence of strings for the first one.
To call a function for each node in an axis step, add it as another one (XPath 2.0 and above only). You can use the dot . (context) in the arguments.
Try something like
./Supplier/matches(., "^(\d{5}\s*)+$")
which will yield true for the third and fifth row. If it only must contain (and not fully constructed from) the repeating pattern of fife-digit-numbers and spaces, remove the ^ and $ from the regular expression.
Try this one: matches(./Supplier, '(.*)((\d{5}(\s*))+)(.*)')

A regular expression about folder name

I want a regular expression to test that a string meets the following rules:
It must not begin with ..
It must not end with ..
It must not include special characters like !##$%^&*, but can include ..
It must not include two dots . side by side.
Sample valid input:
na.me (single dot in middle)
Sample invalid input:
.name (begins with dot)
name. (ends with dot)
na..me (includes two dots side-by-side)
$name (special character not allowed in any position)
name# (likewise)
na#me (likewise)
I believe this should work:
^(\w+\.?)*\w+$
If not in ECMAScript, then replace the \w's with [a-zA-Z_0-9].
The approach here is that instead of citing what's NOT acceptable, it's easier to cite what's acceptable.
Translation of the expression is:
Start with one or many letters, followed by zero or one period (.)
All of which can occur zero or many times
End with at least one letter

Regex to parse international floating-point numbers

I need a regex to get numeric values that can be
111.111,11
111,111.11
111,111
And separate the integer and decimal portions so I can store in a DB with the correct syntax
I tried ([0-9]{1,3}[,.]?)+([,.][0-9]{2})? With no success since it doesn't detect the second part :(
The result should look like:
111.111,11 -> $1 = 111111; $2 = 11
First Answer:
This matches #,###,##0.00:
^[+-]?[0-9]{1,3}(?:\,?[0-9]{3})*(?:\.[0-9]{2})?$
And this matches #.###.##0,00:
^[+-]?[0-9]{1,3}(?:\.?[0-9]{3})*(?:\,[0-9]{2})?$
Joining the two (there are smarter/shorter ways to write it, but it works):
(?:^[+-]?[0-9]{1,3}(?:\,?[0-9]{3})*(?:\.[0-9]{2})?$)
|(?:^[+-]?[0-9]{1,3}(?:\.?[0-9]{3})*(?:\,[0-9]{2})?$)
You can also, add a capturing group to the last comma (or dot) to check which one was used.
Second Answer:
As pointed by Alan M, my previous solution could fail to reject a value like 11,111111.00 where a comma is missing, but the other isn't. After some tests I reached the following regex that avoids this problem:
^[+-]?[0-9]{1,3}
(?:(?<comma>\,?)[0-9]{3})?
(?:\k<comma>[0-9]{3})*
(?:\.[0-9]{2})?$
This deserves some explanation:
^[+-]?[0-9]{1,3} matches the first (1 to 3) digits;
(?:(?<comma>\,?)[0-9]{3})? matches on optional comma followed by more 3 digits, and captures the comma (or the inexistence of one) in a group called 'comma';
(?:\k<comma>[0-9]{3})* matches zero-to-any repetitions of the comma used before (if any) followed by 3 digits;
(?:\.[0-9]{2})?$ matches optional "cents" at the end of the string.
Of course, that will only cover #,###,##0.00 (not #.###.##0,00), but you can always join the regexes like I did above.
Final Answer:
Now, a complete solution. Indentations and line breaks are there for readability only.
^[+-]?[0-9]{1,3}
(?:
(?:\,[0-9]{3})*
(?:.[0-9]{2})?
|
(?:\.[0-9]{3})*
(?:\,[0-9]{2})?
|
[0-9]*
(?:[\.\,][0-9]{2})?
)$
And this variation captures the separators used:
^[+-]?[0-9]{1,3}
(?:
(?:(?<thousand>\,)[0-9]{3})*
(?:(?<decimal>\.)[0-9]{2})?
|
(?:(?<thousand>\.)[0-9]{3})*
(?:(?<decimal>\,)[0-9]{2})?
|
[0-9]*
(?:(?<decimal>[\.\,])[0-9]{2})?
)$
edit 1: "cents" are now optional;
edit 2: text added;
edit 3: second solution added;
edit 4: complete solution added;
edit 5: headings added;
edit 6: capturing added;
edit 7: last answer broke in two versions;
I would at first use this regex to determine wether a comma or a dot is used as a comma delimiter (It fetches the last of the two):
[0-9,\.]*([,\.])[0-9]*
I would then strip all of the other sign (which the previous didn't match). If there were no matches, you already have an integer and can skip the next steps. The removal of the chosen sign can easily be done with a regex, but there are also many other functions which can do this faster/better.
You are then left with a number in the form of an integer possible followed by a comma or a dot and then the decimals, where the integer- and decimal-part easily can be separated from eachother with the following regex.
([0-9]+)[,\.]?([0-9]*)
Good luck!
Edit:
Here is an example made in python, I assume the code should be self-explaining, if it is not, just ask.
import re
input = str(raw_input())
delimiterRegex = re.compile('[0-9,\.]*([,\.])[0-9]*')
splitRegex = re.compile('([0-9]+)[,\.]?([0-9]*)')
delimiter = re.findall(delimiterRegex, input)
if (delimiter[0] == ','):
input = re.sub('[\.]*','', input)
elif (delimiter[0] == '.'):
input = re.sub('[,]*','', input)
print input
With this code, the following inputs gives this:
111.111,11
111111,11
111,111.11
111111.11
111,111
111,111
After this step, one can now easily modify the string to match your needs.
How about
/(\d{1,3}(?:,\d{3})*)(\.\d{2})?/
if you care about validating that the commas separate every 3 digits exactly,
or
/(\d[\d,]*)(\.\d{2})?/
if you don't.
If I'm interpreting your question correctly so that you are saying the result SHOULD look like what you say is "would" look like, then I think you just need to leave the comma out of the character class, since it is used as a separator and not a part of what is to be matched.
So get rid of the "." first, then match the two parts.
$value = "111,111.11";
$value =~ s/\.//g;
$value =~ m/(\d+)(?:,(\d+))?/;
$1 = leading integers with periods removed
$2 = either undef if it didn't exist, or the post-comma digits if they do exist.
See Perl's Regexp::Common::number.