Regular expression for checking every substring - regex

I had this question in my end semester exam, unfortunately I couldn't solve it and tried it for several days and no luck.
Condition- For every substring of length 4 in a string of length n, write a RE to force the rule- there must be exactly three 1's.
My solution kind of looked like
(1+11+111+€)(0111)*(0+€).
But this is obviously wrong, string 11011 is a valid solution too.
Update- my new solution is (1+11+111+€)(0111)*(0+01+011+€).
Update- the plus operator is actually 'OR'
Update- € is empty string
Update - the string length has no requirements. A string of length 5 will have 2 substrings of length 4, the first 4 chars and the last 4 chars

I think the professor is looking for the realization that in order for the condition to hold, a 1 may never be bracketed by zeros on both sides.
(0?11)*
To complete the picture, we also need to include the case for n=1 where either a 0 or a 1 is allowed (I presume).
^[01]$|(0?11)*
I'm using traditional regex here, where [...] denotes a character class, | is "or", parentheses do grouping, and * specifies zero or more repetitions (Kleene star).

Edit: Consider the following regular expression where € refers to the empty string and assuming the alphabet consists of only {0,1,€}:
€ + (0111)* + (1110)* + (1101)* + (1011)*

Python 2
import re
# regular expression
# '^' in the start of the expression means from the very start of the string
# "[^1.]*" means match any character unless it is '1'
# '$' in the end of the expression means till the very end of the string
# Summary:
# from the start of the string till the end of it check if we have
# '1' exactly 3 times,
# and before or after them you might find any type of characters
# and these characters must not be equal '1' ...
expression = '^[^1.]*1[^1.]*1[^1.]*1[^1.]*$'
# testing strings
tests = ["01110", "11100", "00111", "010101", "00100100111", "00100"]
prog = re.compile(expression)
for test in tests:
print 'matched' if prog.match(test) else 'not matched'

Related

Regex split string by two consecutive pipe ||

I want to split below string by two pipe(|| ) regex .
Input String
value1=data1||value2=da|ta2||value3=test&user01|
Expected Output
value1=data1
value2=da|ta2
value3=test&user01|
I tried ([^||]+) but its consider single pipe | also to split .
Try out my example - Regex
value2 has single pipe it should not be considered as matching.
I am using lua script like
for pair in string.gmatch(params, "([^||]+)") do
print(pair)
end
You can explicitly find each ||.
$ cat foo.lua
s = 'value1=data1||value2=da|ta2||value3=test&user01|'
offset = 1
for idx in string.gmatch(s, '()||') do
print(string.sub(s, offset, idx - 1) )
offset = idx + 2
end
-- Deal with the part after the right-most `||`.
-- Must +1 or it'll fail to handle s like "a=b||".
if offset <= #s + 1 then
print(string.sub(s, offset) )
end
$ lua foo.lua
value1=data1
value2=da|ta2
value3=test&user01|
Regarding ()|| see Lua's doc about Patterns (Lua does not have regex support) —
Captures:
A pattern can contain sub-patterns enclosed in parentheses; they describe captures. When a match succeeds, the substrings of the subject string that match captures are stored (captured) for future use. Captures are numbered according to their left parentheses. For instance, in the pattern "(a*(.)%w(%s*))", the part of the string matching "a*(.)%w(%s*)" is stored as the first capture, and therefore has number 1; the character matching "." is captured with number 2, and the part matching "%s*" has number 3.
As a special case, the capture () captures the current string position (a number). For instance, if we apply the pattern "()aa()" on the string "flaaap", there will be two captures: 3 and 5.
the easiest way is to replace the sequence of 2 characters || with any other character (e.g. ;) that will not be used in the data, and only then use it as a separator:
local params = "value1=data1||value2=da|ta2||value3=test&user01|"
for pair in string.gmatch(params:gsub('||',';'), "([^;]+)") do
print(pair)
end
if all characters are possible, then any non-printable characters can be used, according to their codes: string.char("10") == "\10" == "\n"
even with code 1: "\1"
string.gmatch( params:gsub('||','\1'), "([^\1]+)" )

Regular Expression for the Pattern?

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

Tcl regular expressions

set d(aa1) 1
set d(aa2) 1
set d(aa3) 1
set d(aa4) 1
set d(aa5) 1
set d(aa6) 1
set d(aa7) 1
set d(aa8) 1
set d(aa9) 1
set d(aa10) 1
set d(aa11) 1
set regexp "a*\[1-9\]"
set res [array names d -glob $regexp]
puts "res = $res"
In this case, the result is:
res = aa11 aa6 aa2 aa7 aa3 aa8 aa4 aa9 aa5 aa1
But when I change the regexp from a*\[1-9\] to a*\[1-10\], the result becomes:
res = aa11 aa10 aa1
You have an error in your character class.
[1-10] does not mean a digit from 1 to 10
It means 1-1, which is a character ranging from 1 to 1 (i.e., simply a 1), or a 0. This explains your output.
to express a digit from 1 to 10, use this: (?:10?|[2-9]) (as one of several ways to do it.
therefore your regex becomes a*(?:10?|[2-9])
note that if your engine does not allow non-capturing group, you need to remove the ?:, for: a*(?:10?|[2-9])
You need to be sure what you're trying to match because glob style matching and regexp style matching are different in many aspects.
From the docs, glob has the following:
* matches any sequence of characters in string, including a null string.
? matches any single character in string.
[chars] matches any character in the set given by chars. If a sequence of the form x-y appears in chars, then any character between x and y, inclusive, will match. When used with -nocase, the end points of the range are converted to lower case first. Whereas {[A-z]} matches _ when matching case-sensitively (since _ falls between the Z and a), with -nocase this is considered like {[A-Za-z]} (and probably what was meant in the first place).
\x matches the single character x. This provides a way of avoiding the special interpretation of the characters *?[]\ in pattern.
Since you are using glob style matching, your current expression (a*\[1-9\]) matches an a, followed by any characters and any one of 1 through 9 (meaning it would also match something like abcjdne1).
If you want to match at least one a followed by numbers from 1 through 10, you will need something like this, using the -regexp mode:
set regexp {a+(?:[1-9]|10)}
set res [array names d -regexp $regexp]
Now, this regexp is I believe the more natural one for a beginner ((?:[1-9]|10) meaning either 1 through 9, or 10, but you can use the form that zx81 suggested with (?:10?|[2-9]) meaning 1, with an optional 0 for 10, or 2 through 9).
+ means that a must appear at least once for the array name to match.
If you now need to match the full names, you will need to use anchors:
^a+(?:[1-9]|10)$
Note: You cannot use glob matching if you want to match at least one a followed by digits, and alternation (the pipe used |) and quantifiers (? or + or *) the way they behave in regexp are not supported by glob matching.
One last thing, use braces to avoid escaping your pattern (unless you have a variable or running a function in your pattern and can't do otherwise).

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

Regular expression help - comma delimited string

I don't write many regular expressions so I'm going to need some help on the one.
I need a regular expression that can validate that a string is an alphanumeric comma delimited string.
Examples:
123, 4A67, GGG, 767 would be valid.
12333, 78787&*, GH778 would be invalid
fghkjhfdg8797< would be invalid
This is what I have so far, but isn't quite right: ^(?=.*[a-zA-Z0-9][,]).*$
Any suggestions?
Sounds like you need an expression like this:
^[0-9a-zA-Z]+(,[0-9a-zA-Z]+)*$
Posix allows for the more self-descriptive version:
^[[:alnum:]]+(,[[:alnum:]]+)*$
^[[:alnum:]]+([[:space:]]*,[[:space:]]*[[:alnum:]]+)*$ // allow whitespace
If you're willing to admit underscores, too, search for entire words (\w+):
^\w+(,\w+)*$
^\w+(\s*,\s*\w+)*$ // allow whitespaces around the comma
Try this pattern: ^([a-zA-Z0-9]+,?\s*)+$
I tested it with your cases, as well as just a single number "123". I don't know if you will always have a comma or not.
The [a-zA-Z0-9]+ means match 1 or more of these symbols
The ,? means match 0 or 1 commas (basically, the comma is optional)
The \s* handles 1 or more spaces after the comma
and finally the outer + says match 1 or more of the pattern.
This will also match
123 123 abc (no commas) which might be a problem
This will also match 123, (ends with a comma) which might be a problem.
Try the following expression:
/^([a-z0-9\s]+,)*([a-z0-9\s]+){1}$/i
This will work for:
test
test, test
test123,Test 123,test
I would strongly suggest trimming the whitespaces at the beginning and end of each item in the comma-separated list.
You seem to be lacking repetition. How about:
^(?:[a-zA-Z0-9 ]+,)*[a-zA-Z0-9 ]+$
I'm not sure how you'd express that in VB.Net, but in Python:
>>> import re
>>> x [ "123, $a67, GGG, 767", "12333, 78787&*, GH778" ]
>>> r = '^(?:[a-zA-Z0-9 ]+,)*[a-zA-Z0-9 ]+$'
>>> for s in x:
... print re.match( r, s )
...
<_sre.SRE_Match object at 0xb75c8218>
None
>>>>
You can use shortcuts instead of listing the [a-zA-Z0-9 ] part, but this is probably easier to understand.
Analyzing the highlights:
[a-zA-Z0-9 ]+ : capture one or more (but not zero) of the listed ranges, and space.
(?:[...]+,)* : In non-capturing parenthesis, match one or more of the characters, plus a comma at the end. Match such sequences zero or more times. Capturing zero times allows for no comma.
[...]+ : capture at least one of these. This does not include a comma. This is to ensure that it does not accept a trailing comma. If a trailing comma is acceptable, then the expression is easier: ^[a-zA-Z0-9 ,]+
Yes, when you want to catch comma separated things where a comma at the end is not legal, and the things match to $LONGSTUFF, you have to repeat $LONGSTUFF:
$LONGSTUFF(,$LONGSTUFF)*
If $LONGSTUFF is really long and contains comma repeated items itself etc., it might be a good idea to not build the regexp by hand and instead rely on a computer for doing that for you, even if it's just through string concatenation. For example, I just wanted to build a regular expression to validate the CPUID parameter of a XEN configuration file, of the ['1:a=b,c=d','2:e=f,g=h'] type. I... believe this mostly fits the bill: (whitespace notwithstanding!)
xend_fudge_item_re = r"""
e[a-d]x= #register of the call return value to fudge
(
0x[0-9A-F]+ | #either hardcode the reply
[10xks]{32} #or edit the bitfield directly
)
"""
xend_string_item_re = r"""
(0x)?[0-9A-F]+: #leafnum (the contents of EAX before the call)
%s #one fudge
(,%s)* #repeated multiple times
""" % (xend_fudge_item_re, xend_fudge_item_re)
xend_syntax = re.compile(r"""
\[ #a list of
'%s' #string elements
(,'%s')* #repeated multiple times
\]
$ #and nothing else
""" % (xend_string_item_re, xend_string_item_re), re.VERBOSE | re.MULTILINE)
Try ^(?!,)((, *)?([a-zA-Z0-9])\b)*$
Step by step description:
Don't match a beginning comma (good for the upcoming "loop").
Match optional comma and spaces.
Match characters you like.
The match of a word boundary make sure that a comma is necessary if more arguments are stacked in string.
Please use - ^((([a-zA-Z0-9\s]){1,45},)+([a-zA-Z0-9\s]){1,45})$
Here, I have set max word size to 45, as longest word in english is 45 characters, can be changed as per requirement