Regular expression to match IRC nickname - regex

How would I use a regular expression to match an IRC nickname? This is being done in Ruby if that makes a difference (it probably will, with the syntax of the regex, but who knows.)
EDIT: An IRC nickname can contain any letter, number, or any of the following characters: <
- [ ] \ ^ { }

# If you are testing a single string
irc_nick_re = /\A[a-z_\-\[\]\\^{}|`][a-z0-9_\-\[\]\\^{}|`]*\z/i
# If you are scanning them out of a larger string
irc_nick_re = /(?<=[^a-z_\-\[\]\\^{}|`])[a-z_\-\[\]\\^{}|`][a-z0-9_\-\[\]\\^{}|`]*/i
The above allows single-character names. If two characters are required, change the * to +. If three characters (or more) are required, change it to {2,}, where '2' is the minimum number of characters minus 1.
If there is a maximum number of characters (for example, EFNet only allows nicknames up to 9 characters lone, while Freenode allows nicks up to 16 characters long) then you can include that number (minus 1) after the comma. For example:
# Validate nicknames that are between 3 and 16 characters long (inclusive)
irc_nick_re = /\A[a-z_\-\[\]\\^{}|`][a-z0-9_\-\[\]\\^{}|`]{2,15}\z/i

Related

Regex: not all BLANKS but allow certain characters, with limit

Trying to come up with a Regex, or combination of Regex, that returns False if a) they have only entered only BLANK(s), or they b) entered "non-legal" characters. Lastly, the number of characters has a set limit.
The closest I have thus far is below. Where it fails is that it does not count any leading spaces; only the non-BLANKs are counted, and so it fails. Using js.
const reg = /^(**[ ]***[!-~\u2018-\u201d\u2013\u2014]){1,10}$/;
EDIT: I think the above is incorrect, and I meant to post this:
const re4 = /^(?!\s*$)[!-~\u2018-\u201d\u2013\u2014]{1,10}$/;
EDIT 2: this has less clutter; allow space and all other 'standard' keyboard chars:
const re5 = /^(?!\s*$)[!-~]{1,10}$/;
So, this says you can enter a bunch of spaces, and must include at least 1 other character from the list following; but the {1,10} only counts the non-spaces and so I can end up with too many in total.
EDIT:
So, using re5 above --
s = ' '; // should fail
s = ' blah blah'; // should pass
s = ' blah blah'; // should fail, as there are 11 characters
Try ^(?:\s*\S){1,10}\s*$
Allow 1-10 non whiter, change \S to allow chars
Update 2: After learning that you cannot invert the match result in code, here's one last suggestion using negative lookahead (like you already tried yourself).
This regex matches only strings of 1-10 non-banned characters that are not all whitespace:
const re4 = /^(?!\s+$)[^\!-\~\u2018-\u201d\u2013\u2014]{1,10}$/
Update 1: Use this regex to match all-whitespace string OR strings longer than 10 chars OR strings containing bad characters:
const re4 = /(^\s+$|^.{11,}$|[\!-\~\u2018-\u201d\u2013\u2014])/
I understand that you want to impose a length restriction via regex. I would suggest against that and recommend using str.length instead.
This regex will match whitespace-only strings and strings containing one or more bad characters:
const re4 = /(^\s+$|[\!-\~\u2018-\u201d\u2013\u2014])/;
Regarding prohibition of all-whitespace strings: Instead of packing it into a regex, you might consider using something more explicit like if (s.trim().length == 0). IMO this makes your intention clearer and your code propably more readable, leaving you with this easy to read regex:
# matches any string containing a *bad* character
const re4 = /[\!-\~\u2018-\u201d\u2013\u2014]/;
If you use trim for the all-whitespace check, you might convert your regex into a positive assertion, even with length restriction:
# matches any string consisting of 1-10 characters not considered *bad*
const re4 = /^[^\!-\~\u2018-\u201d\u2013\u2014]{1,10}$/;
To match the input when it’s from 1 to 10 chars long and can't be all blanks, use a negative look ahead to assert not all blanks:
^(?! *$).{1,10}
If you want to restrict allowable chars, change the dot to a suitable character class of allowable chars.

Regular expression for checking every substring

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'

RegEx for company name variations

I have a requirement to accept string values ONLY where they meet the following criteria :
1) Can start with special character if required
2) Must start with capital letter ( Even if the first character is a special character )
3) The string value must not have 2 special characters in a row ( consecutive )
4) The string value must not have 2 spaces in a row ( consecutive )
5) Accented characters are allowed ( eg: Faddas )
6) Enclosed values at the start of the string or at the end are valid but must be inside parenthesis ( ie: (Ltd) )
7) Numerics are allowed anywhere in the string value
I have the following regex value : ^(\(([^)]+)\))?[\#\#\$\%\&\*\(\)\-\_\+\]\[\'\;\:\?\.\,\!]?\p{Lu}+[\s'-]?\p{L}+(?:[\s'-]\p{L}+)+(\(([^)]+)\))*$
This works ok for the following tested values :
Éast-Shipping-ltd
Éast-Shipping(LTD)
But fails the next example :
Éast-123Shipping(LTD)
Is there any way to allow for numerics mid string ?
I have tried [0-9] variations, [A-Za-z09] variations and p{N} variations but to no avail.
Many thanks for your time.
This is a REALLY nasty pattern, but I was able to simplify it a bit and do what you wanted:
^(\(([^)]+)\))?[[:punct:]]?\p{Lu}+(?:[\s'-]?[\p{L}\d]+)+(\(([^)]+)\))*$
There are lots of useful shorthand character classes, including [[:punct:]], which I used to replace your massive punctuation character class. To add the ability to include numbers, I put the \p{L} in a character class with the \d token, which will match any number (in any language, with the Unicode flag).
Demo on Regex101
Here we have some characters acceptable for company names
^[0-9A-Za-zÀ-ÿ\s,._+;()*~'##!?&-]+$

What would be a regular expression that can test if a string is a valid Firebase key?

I'm writing an application that allows users to input values that will be stored in Firebase as a key.
Firebase Key Requirement:
max size - 768 bytes
cannot contain . $ # [ ] / or ASCII control characters 0-31 or 127
allows single spaces, but not double or more spaces
How can I express this as a regular expression?
Assuming 1 byte = 1 character, and since you mention ASCII, assuming the valid characters are ASCII characters 32 through 126.
"Match any of these allowed characters, exactly 768 times":
[ !"%&'()*+\,\-\/0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ\^_`abcdefghijklmnopqrstuvwxyz{|}]{768}
https://regex101.com/r/lQ2gJ4/2
Edit
That didn't work because I missed the need to block consecutive spaces. New suggestion, with a basic pattern of:
# a space, not followed by a space
# or a character not followed by a double-space.
# This pattern, matched n times, locking the start and end of the string.
^( (?! )|[a](?! )){5}$
However, when I substitute the full character set in...
^( (?! )|[ !"%&'()*+\,\-\/0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ\^_`abcdefghijklmnopqrstuvwxyz{|}](?! )){1,768}$
# it breaks Regex101, saying it's too large.
NB. It's much easier without RegEx:
# Python example validator
def validate(s):
valid_chars = 'abc123...'
if not (0 < len(s) <= 768): return False
if ' ' in s: return False
for char in s: if char not in valid_chars: return False
return True
You haven't provided a use case, and you may need more if this is a sever-side app with some complex inputs, but generally speaking, one isn't concerned about control characters in input since that would be someone tinkering about and trying to break things, and would be rejected accordingly by the SDK.
So the Firebase team generally just focuses on the invalid, keyboard-producible characters:
// in JavaScript
function isValidKey(text) {
return typeof text === 'string' &&
text.length &&
!text.match(/[.$\[\]#\/]/);
}
There are a couple exceptions: .value, .priority, and .info are valid keys in Firebase, but only for accessing special meta data and not as a record id.
Side note: I don't see anything in the docs about double spaces.

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