I want to limit levels of subdomain to 3 levels only. trying regex below fails
([\.]?[a-z]*){3}
My Target: abc.def.ghi
but
regex above accepts abc.def.ghi. (Notice the last .)
Use
^(?:[a-z]+(?:\.[a-z]+){0,2})?$
See proof.
Explanation
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
(?: group, but do not capture (optional
(matching the most amount possible)):
--------------------------------------------------------------------------------
[a-z]+ any character of: 'a' to 'z' (1 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
(?: group, but do not capture (between 0 and
2 times (matching the most amount
possible)):
--------------------------------------------------------------------------------
\. '.'
--------------------------------------------------------------------------------
[a-z]+ any character of: 'a' to 'z' (1 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
){0,2} end of grouping
--------------------------------------------------------------------------------
)? end of grouping
--------------------------------------------------------------------------------
$ before an optional \n, and the end of the
string
Related
I'm trying to get only h1 and h2 headers from markdown file using regex, but unfortunately I don't know regex well and can't write the correct solution.
With this expression I'm near the solution (I think so):
/\#{1,2} (.*?)(\\r\\n|\\r|\\n)/gm
But it returns also headers with more than two hashes.
Test case:
# first \r
## second \r
### third \r## fourth \r
This should return ['first', 'second', 'fourth']
Use
/(?<!#)#{1,2} (.*?)(\\r(?:\\n)?|\\n)/gm
See regex proof.
EXPLANATION
--------------------------------------------------------------------------------
(?<! look behind to see if there is not:
--------------------------------------------------------------------------------
# '#'
--------------------------------------------------------------------------------
) end of look-behind
--------------------------------------------------------------------------------
#{1,2} '#' (between 1 and 2 times (matching the
most amount possible))
--------------------------------------------------------------------------------
' '
--------------------------------------------------------------------------------
( group and capture to \1:
--------------------------------------------------------------------------------
.*? any character except \n (0 or more times
(matching the least amount possible))
--------------------------------------------------------------------------------
) end of \1
--------------------------------------------------------------------------------
( group and capture to \2:
--------------------------------------------------------------------------------
\\ '\'
--------------------------------------------------------------------------------
r 'r'
--------------------------------------------------------------------------------
(?: group, but do not capture (optional
(matching the most amount possible)):
--------------------------------------------------------------------------------
\\ '\'
--------------------------------------------------------------------------------
n 'n'
--------------------------------------------------------------------------------
)? end of grouping
--------------------------------------------------------------------------------
| OR
--------------------------------------------------------------------------------
\\ '\'
--------------------------------------------------------------------------------
n 'n'
--------------------------------------------------------------------------------
) end of \2
So right now I can isolate each JSDoc (ish) block I have in my code, for example I have this block here
/// #tag {type} name description
/// description continue
/// another description line
/// #tag {type} name description
/// description continue
/// #tag name description just one line.
/// #tag {type} name
I want to use a Regex expression to match each tag inside the block a tag needs to have a #name format then it can have a type {type} (optional) then it requires a name and finally it can have a description.. the description can be both multiple lined or single lined (and is also optional). So
the Regex I have came up with was:
^\/{3} #(?<tag>\w+)(?:[ \t]+{(?<type>.*)})?(?:[ \t]+(?<name>\w+))(?:[ \t]+(?<desc>[\s\S]*))?
my problem is with the description as soon as I hit the description it doesn't stop at the start of the next tag... I get the feeling that right now I'm using a greedy approach but I cannot find a wait to make it non greedy.
So the example above matches:
tag: tag
name: name
description:
description
/// description continue
/// another description line
/// #tag {type} name description
/// description continue
/// #tag name description just one line.
/// #tag {type} name
I wanted the description to stop just as the new tag starts or if the block ends
Use
/^\/{3} #(?<tag>\w+)(?:[ \t]+{(?<type>[^{}]*)})?[ \t]+(?<name>\w+)(?:[ \t]+(?<desc>.*(?:\n(?!\/{3} #\w).*)*))?/gm
See regex proof.
EXPLANATION
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
\/{3} '/' (3 times)
--------------------------------------------------------------------------------
# ' #'
--------------------------------------------------------------------------------
(?<tag> group and capture to \k<tag>:
--------------------------------------------------------------------------------
\w+ word characters (a-z, A-Z, 0-9, _) (1 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
) end of \k<tag>
--------------------------------------------------------------------------------
(?: group, but do not capture (optional
(matching the most amount possible)):
--------------------------------------------------------------------------------
[ \t]+ any character of: ' ', '\t' (tab) (1 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
{ '{'
--------------------------------------------------------------------------------
(?<type> group and capture to \k<type>:
--------------------------------------------------------------------------------
[^{}]* any character except: '{', '}' (0 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
) end of \k<type>
--------------------------------------------------------------------------------
} '}'
--------------------------------------------------------------------------------
)? end of grouping
--------------------------------------------------------------------------------
[ \t]+ any character of: ' ', '\t' (tab) (1 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
(?<name> group and capture to \k<name>:
--------------------------------------------------------------------------------
\w+ word characters (a-z, A-Z, 0-9, _) (1 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
) end of \k<name>
--------------------------------------------------------------------------------
(?: group, but do not capture (optional
(matching the most amount possible)):
--------------------------------------------------------------------------------
[ \t]+ any character of: ' ', '\t' (tab) (1 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
(?<desc> group and capture to \k<desc>:
--------------------------------------------------------------------------------
.* any character except \n (0 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
(?: group, but do not capture (0 or more
times (matching the most amount
possible)):
--------------------------------------------------------------------------------
\n '\n' (newline)
--------------------------------------------------------------------------------
(?! look ahead to see if there is not:
--------------------------------------------------------------------------------
\/{3} '/' (3 times)
--------------------------------------------------------------------------------
# ' #'
--------------------------------------------------------------------------------
\w word characters (a-z, A-Z, 0-9, _)
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
.* any character except \n (0 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
)* end of grouping
--------------------------------------------------------------------------------
) end of \k<desc>
--------------------------------------------------------------------------------
)? end of grouping
Yep, the problem is that the description matcher is greedy. Changing * to *? to make it non-greedy fixes it. But it still has the problem of knowing when to stop. You can do that by checking if the input is over, or if there is a /// # ahead. Note that this includes the /// at the start of each description line: I don't think it's possible to filter them out directly in the regex, so you'd have to post-process the output to remove ///s in desc.
/^\/{3} #(?<tag>\w+)(?:[ \t]+{(?<type>.*)})?(?:[ \t]+(?<name>\w+))((?:[ \t]+(?<desc>[\s\S]*?)((?=\/\/\/ #)|\s*\z)))?/gm
I have a university assignment to write a JS regex for name validation: name can include spaces at the beginning and the end (don't ask anything, it's our teacher demand), also it can include such chars like: -, ' and space (" "). At the moment, my regex looks like that:
var Nameregex = /^( ?)*[A-Z]+((['-])?[a-z]+)*(([ ]?[a-z]*)*)*$/g;
It works almost perfect, but except for one case: one word (words separated from each other with spaces and - symbols) can contain only one ' symbol.
For example, names like John-andrew'andrew'john shouldn't work. But John-andrew'john-andrew'john should work.
Add a (?!.*'[A-Za-z]+') negative lookahead after ^:
/^(?!.*'[A-Za-z]+')\s*[A-Z]+(?:['-]?[a-z]+)*(?:\s*[a-z]*)*$/
See proof
Explanation
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
(?! look ahead to see if there is not:
--------------------------------------------------------------------------------
.* any character except \n (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
' '\''
--------------------------------------------------------------------------------
[A-Za-z]+ any character of: 'A' to 'Z', 'a' to 'z'
(1 or more times (matching the most
amount possible))
--------------------------------------------------------------------------------
' '\''
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
\s* whitespace (\n, \r, \t, \f, and " ") (0 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
[A-Z]+ any character of: 'A' to 'Z' (1 or more
times (matching the most amount possible))
--------------------------------------------------------------------------------
(?: group, but do not capture (0 or more times
(matching the most amount possible)):
--------------------------------------------------------------------------------
['-]? any character of: ''', '-' (optional
(matching the most amount possible))
--------------------------------------------------------------------------------
[a-z]+ any character of: 'a' to 'z' (1 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
)* end of grouping
--------------------------------------------------------------------------------
(?: group, but do not capture (0 or more times
(matching the most amount possible)):
--------------------------------------------------------------------------------
\s* whitespace (\n, \r, \t, \f, and " ") (0
or more times (matching the most amount
possible))
--------------------------------------------------------------------------------
[a-z]* any character of: 'a' to 'z' (0 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
)* end of grouping
--------------------------------------------------------------------------------
$ before an optional \n, and the end of the
string
I want to remove symbols in phone numbers. Sometimes it is in the format of 151-454-6545 but sometimes it is in (545)-(564)-(5465) and in sometimes it is in 548.445.8454. I am using
val.replace(/(\d{3})(\d{3})(\d{4})/, '($1) -$2-$3')
for replacing.. but it doesn't remove the dot.What to do remove the dot also? expected output like 545-455-4545
I suggest to use a non-digit expression to replace them by '-' string :
val.replace(/^\D+/, '')
.replace(/\D+$/, '')
.replace(/\D+/g, '-')
Let me know if it does what you need.
EDIT : trim whitespaces
here is a version with only 1 regex
https://regex101.com/r/Wavw45/1
regex
[^\d\n]*(\d{3})[^\d\n]+(\d{3,4})[^\d\n]+(\d{4})[^\d\n]*
replace (or whatever pattern you want)
($1) -$2-$3
Use
.replace(/^\D*(\d{3})\D*(\d{3})\D*(\d{4})\D*$/, '$1-$2-$3')
See proof.
Explanation
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
\D* non-digits (all but 0-9) (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
( group and capture to \1:
--------------------------------------------------------------------------------
\d{3} digits (0-9) (3 times)
--------------------------------------------------------------------------------
) end of \1
--------------------------------------------------------------------------------
\D* non-digits (all but 0-9) (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
( group and capture to \2:
--------------------------------------------------------------------------------
\d{3} digits (0-9) (3 times)
--------------------------------------------------------------------------------
) end of \2
--------------------------------------------------------------------------------
\D* non-digits (all but 0-9) (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
( group and capture to \3:
--------------------------------------------------------------------------------
\d{4} digits (0-9) (4 times)
--------------------------------------------------------------------------------
) end of \3
--------------------------------------------------------------------------------
\D* non-digits (all but 0-9) (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
$ before an optional \n, and the end of the
string
I am attempting to validate text input with the following requirements:
allowed characters & length /^\w{8,15}$/
must contain /[a-z]+/
must contain /[A-Z]+/
must contain /[0-9]+/
must not contain repeated characters (ie. aba=pass and aab=fail)
Each test would return true when used with .test().
With modest familiarity, I am able to write the first 4 tests, albeit individually. The 5th test is not working out, negated lookahead (which is what i believe i need to be using) is challenging.
Here are a few value/result examples:
re.test("Fail1");//returns false, too short
re.test("StringFailsRule1");//returns false, too long
re.test("Fail!");//returns false, invalid !
re.test("FAILRULE2");//returns false, missing [a-z]+
re.test("failrule3");//returns false, missing [A-Z]+
re.test("failRuleFour");//returns false, missing [0-9]+
re.test("failRule55");//returns false, repeat of "5"
re.test("TestValue1");//returns true
Finally, the ideal would be a single combined test used to enforce all requirements.
This uses negative and positive lookaheads zero-length assertions for your tests and the .{8,15} bit validates length.
^(?!.*(.)\1)(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])\w{8,15}$
For your fifth rule I used a negative lookahead to make sure that a capture group of any character is never followed by itself.
Regexpal demo
NODE EXPLANATION
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
(?! look ahead to see if there is not:
--------------------------------------------------------------------------------
.* any character except \n (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
( group and capture to \1:
--------------------------------------------------------------------------------
. any character except \n
--------------------------------------------------------------------------------
) end of \1
--------------------------------------------------------------------------------
\1 what was matched by capture \1
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
(?= look ahead to see if there is:
--------------------------------------------------------------------------------
.* any character except \n (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
[a-z] any character of: 'a' to 'z'
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
(?= look ahead to see if there is:
--------------------------------------------------------------------------------
.* any character except \n (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
[A-Z] any character of: 'A' to 'Z'
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
(?= look ahead to see if there is:
--------------------------------------------------------------------------------
.* any character except \n (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
[0-9] any character of: '0' to '9'
--------------------------------------------------------------------------------
) end of look-ahead
--------------------------------------------------------------------------------
\w{8,15} word characters (a-z, A-Z, 0-9, _)
(between 8 and 15 times (matching the most
amount possible))
--------------------------------------------------------------------------------
$ before an optional \n, and the end of the
string