my collegue and I try to build a Regex (Javascript) to validate an input field for a specific format.
The field should be a comma seperated list of port declarations and could look like this:
TCP/53,UDP/53,TCP/10-20,UDP/20-30
We tried this regex:
/^[TCP/\d+,|UDP/\d+,|TCP/\d+\-\d+,|UDP/\d+\-\d+,]*[TCP/\d+|UDP/\d+|TCP/\d+\-\d+|UDP/\d+\-\d+]$/g
the regex matches, but also matches other strings as well, like this one:
TCP/53UDP53,TCP/10-20UDP20-30
Thanks for any guidance!
You don't need all those alternations, and the [ ] are not used for grouping like that. You can also make the - and digits part optional using grouping (?:...)?
To match that string format:
^(?:TCP|UDP)\/\d+(?:-\d+)?(?:,(?:TCP|UDP)\/\d+(?:-\d+)?)*$
The pattern matches:
^ Start of string
(?:TCP|UDP) Match one of the alternatives
\/\d+(?:-\d+)? Match / 1+ digits and optionally - and 1+ digits
(?: Non capture group to repeat as a whole part
,(?:TCP|UDP)\/\d+(?:-\d+)? Match a , and repeat the same pattern
)* Close non capture group and optionally repeat (If there should be at least 1 comma, change the * to +)
$ End of string
Regex demo
Alternative: split up the string, use Array.filter and a relative simple RegExp for testing.
const valid = `TCP/53,UDP/53,TCP/10-20,UDP/20-30`;
const invalid = `TCP/53UDP53,TCP/10-20UDP20-30`;
console.log(`${valid} ok? ${checkInp(valid)}`);
console.log(`${invalid} ok? ${checkInp(invalid)}`);
function checkInp(str) {
return str.split(`,`)
.filter(v => /^(TCP|UDP)\/\d+(?:-\d+)*$/.test(v))
.join(`,`)
.length === str.length;
}
Related
So as an exercise I wanted to match any JS number. This is the one I could come up with:
/^(-?)(0|([1-9]\d*?|0)(\.\d+)?)$/
This however doesn't match the new syntax with underscore separators (1_2.3_4). I tried a couple of things but I couldn't come up with something that would work. How could I express all JS numbers in one regex?
For the format in the question, you could use:
^-?\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?$
See a regex demo.
Or allowing only a single leading zero:
^-?(?:0|[1-9]\d*)(?:_\d+)*(?:\.\d+(?:_\d+)*)?$
The pattern matches:
^ Start of string
-? Match an optional -
(?:0|[1-9]\d*) Match either 0 or 1-9 and optional digits
(?:_\d+)* Optionally repeat matching _ and 1+ digits
(?: Non capture group
\.\d+(?:_\d+)* Match . and 1+ digits and optionally repeat matching _ and 1+ digits
)? Close non capture group
$ End of string
See another regex demo.
how about this?
^(-?)(0|([1-9]*?(\_)?(\d)|0|)(\.\d+)?(\_)?(\d))$
I am trying to validate aws arn for a connect instance but I am stuck on creating the correct regex.
Below is the string that I want to validate.
arn:aws:connect:us-west-2:123456789011:instance/0533yu22-d4cb-410a-81da-6c9hjhjucec4b9
I want to create a regex which checks below things.
arn:aws:connect:<region_name>:<12 digit account id>:instance/<an alphanumeric instance id>
Can someone please help.
Tried below
^arn:aws:connect:\S+:\d+:instance\/\S+\/queue\/\S+$
There is no /queue/ substring in your example string, and \S+ matches any no whitespace character and will cause backtracking to match the rest of the pattern.
You might update your pattern to ^arn:aws:connect:\S+:\d+:instance\/\S+$ but that will be less precise according to the things you want to check.
A bit more precise pattern could be:
^arn:aws:connect:\w+(?:-\w+)+:\d{12}:instance\/[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+$
^ Start of string
arn:aws:connect: Match literally
\w+(?:-\w+)+: Match 1+ word characters and repeat matching - and 1+ word characters and then match :
\d{12}: Match 12 digits and :
instance\/ Match instance/
[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+ Match 1+ alpha numerics and repeat 1+ times - and 1+ alpha numerics
$ End of string
Regex demo
You need some capture groups to facilitate this. Here I've also used named capture groups for ease of understanding.
const string = "arn:aws:connect:us-west-2:123456789011:instance/0533yu22-d4cb-410a-81da-6c9hjhjucec4b9";
// Regex broken down into parts
const parts = [
'arn:aws:connect:',
'(?<region_name>[^:]+?)', // group 1
':',
'(?<account_id>\\d{12})', // group 2
':instance\\/',
'(?<instance_id>[A-z0-9\\-]+?)', // group 3
'$'
];
// Joined parts into regex expression
const regex = new RegExp(parts.join(''));
// Execute query and assign group values to variables
const { region_name, account_id, instance_id } = regex.exec(string).groups;
console.log("region_name:", region_name);
console.log("account_id:", account_id);
console.log("instance_id:", instance_id);
I am newbie in RegEx and trying to design a RegEx which could match the String like below:
pattern 1 separated by comma and a space: KEPM39, JEMGH5, HEPM21 ... (repeat)
pattern 2 separated only by a space: KEPM39 JEMGH5 HEPM21 ... (repeat)
pattern 3 separated only by a comma: KEPM39,JEMGH5,HEPM21 ... (repeat)
this is my concept: "^[a-zA-Z0-9]{6,}[,\s]+$" but it seems wrong.
#I want to validate the whole string, and I use javascript & html to validate user input. (textarea)
#duplicate change to repeat to be more suitable.
function validate(){
var term = "JEPM34, KEPM11 ";
var re = new RegExp("^[a-zA-Z0-9]{6,}[,\s]+$");
if (re.test(term)) {
return true
} else {
return false
}
}
thanks you in advance!
A very loose way to validate could be:
^[A-Z\d]{6}(?:[ ,]+[A-Z\d]{6})*$
See the online demo. With loose, I meant that [ ,]+ is not checking that each delimiter in your string is the same per definition. Therefor even "KEPM39, JEMGH5 HEPM21, HEGD44 ZZZZZZ" would be valid.
If you want consistent delimiters, and there can be trailing spaces (as there is in your example data) you can use a capture group with a backreference \1 to keep consistent delimiters and match optional spaces at the end.
Note that you can also use \s but that could also match a newline.
Using test will return a boolean, so you don't have to use return true or false but you can return the result test`
^[A-Z\d]{6}(?:(, ?| )(?:[A-Z\d]{6}\1)*[A-Z\d]{6} *)?$
The pattern matches:
^ Start of string
[A-Z\d]{6} Match 6 occurrences of a char A-Z or a digit
(?: Non capture group to match as a whole
(, ?| ) Capture group 1, match either a comma and optional space, or a space to be used as a backreference
(?:[A-Z\d]{6}\1)* Optionally repeat any of the listed followed by a backreference \1 to group 1 which will match the same delimiter
[A-Z\d]{6} * Match any of the listed and optional spaces at the end
)? Close the group and make it optional to also match an instance without delimiters
$ End of string
Regex demo
const regex = /^[A-Z\d]{6}(?:(, ?| )(?:[A-Z\d]{6}\1)*[A-Z\d]{6} *)?$/;
const validate = term => regex.test(term);
[
"KEPM39, JEMGH5, HEPM21",
"KEPM39 JEMGH5 HEPM21",
"KEPM39,JEMGH5,HEPM21",
"JEPM34, KEPM11 ",
"JEPM34, KEPM11",
"JEPM34",
"KEPM39, JEMGH5 HEPM21, HEGD44 ZZZZZZ",
"KEPM39, JEMGH5 HEPM21"
].forEach(s =>
console.log(`${s} ==> ${validate(s)}`)
);
I'm trying to create a regex using javascript that will allow names like abc-def but will not allow abc-
(hyphen is also the only nonalpha character allowed)
The name has to be a minimum of 2 characters. I started with
^[a-zA-Z-]{2,}$, but it's not good enough so I'm trying something like this
^([A-Za-z]{2,})+(-[A-Za-z]+)*$.
It can have more than one - in a name but it should never start or finish with -.
It's allowing names like xx-x but not names like x-x. I'd like to achieve that x-x is also accepted but not x-.
Thanks!
Option 1
This option matches strings that begin and end with a letter and ensures two - are not consecutive so a string like a--a is invalid. To allow this case, see the Option 2.
^[a-z]+(?:-?[a-z]+)+$
^ Assert position at the start of the line
[a-z]+ Match any lowercase ASCII letter one or more times (with i flag this also matches uppercase variants)
(?:-?[a-z]+)+ Match the following one or more times
-? Optionally match -
[a-z]+ Match any ASCII letter (with i flag)
$ Assert position at the end of the line
var a = [
"aa","a-a","a-a-a","aa-aa-aa","aa-a", // valid
"aa-a-","a","a-","-a","a--a" // invalid
]
var r = /^[a-z]+(?:-?[a-z]+)+$/i
a.forEach(function(s) {
console.log(`${s}: ${r.test(s)}`)
})
Option 2
If you want to match strings like a--a then you can instead use the following regex:
^[a-z]+[a-z-]*[a-z]+$
var a = [
"aa","a-a","a-a-a","aa-aa-aa","aa-a","a--a", // valid
"aa-a-","a","a-","-a" // invalid
]
var r = /^[a-z]+[a-z-]*[a-z]+$/i
a.forEach(function(s) {
console.log(`${s}: ${r.test(s)}`)
})
You can use a negative lookahead:
/(?!.*-$)^[a-z][a-z-]+$/i
Regex101 Example
Breakdown:
// Negative lookahead so that it can't end with a -
(?!.*-$)
// The actual string must begin with a letter a-z
[a-z]
// Any following strings can be a-z or -, there must be at least 1 of these
[a-z-]+
let regex = /(?!.*-$)^[a-z][a-z-]+$/i;
let test = [
'xx-x',
'x-x',
'x-x-x',
'x-',
'x-x-x-',
'-x',
'x'
];
test.forEach(string => {
console.log(string, ':', regex.test(string));
});
The problem is that the first assertion accepts 2 or more [A-Za-z]. You will need to modify it to accept one or more character:
^[A-Za-z]+((-[A-Za-z]{1,})+)?$
Edit: solved some commented issues
/^[A-Za-z]+((-[A-Za-z]{1,})+)?$/.test('xggg-dfe'); // Logs true
/^[A-Za-z]+((-[A-Za-z]{1,})+)?$/.test('x-d'); // Logs true
/^[A-Za-z]+((-[A-Za-z]{1,})+)?$/.test('xggg-'); // Logs false
Edit 2: Edited to accept characters only
/^[A-Za-z]+((-[A-Za-z]{1,})+)?$/.test('abc'); // Logs true
Use this if you want to accept such as A---A as well :
^(?!-|.*-$)[A-Za-z-]{2,}$
https://regex101.com/r/4UYd9l/4/
If you don't want to accept such as A---A do this:
^(?!-|.*[-]{2,}.*|.*-$)[A-Za-z-]{2,}$
https://regex101.com/r/qH4Q0q/4/
So both will accept only word starting from two characters of the pattern [A-Za-z-] and not start or end (?!-|.*-$) (negative lookahead) with - .
Try this /([a-zA-Z]{1,}-[a-zA-Z]{1,})/g
I suggest the following :
^[a-zA-Z][a-zA-Z-]*[a-zA-Z]$
It validates :
that the matched string is at least composed of two characters (the first and last character classes are matched exactly once)
that the first and the last characters aren't dashes (the first and last character classes do not include -)
that the string can contain dashes and be greater than 2 characters (the second character class includes dashes and will consume as much characters as needed, dashes included).
Try it online.
^(?=[A-Za-z](?:-|[A-Za-z]))(?:(?:-|^)[A-Za-z]+)+$
Asserts that
the first character is a-z
the second is a-z or hyphen
If this matches
looks for groups of one or more letters prefixed by a hyphen or start of string, all the way to end of string.
You can also use the I switch to make it case insensitive.
I would like to test if user type only alphanumeric value or one "-".
hello-world -> Match
hello-first-world -> match
this-is-my-super-world -> match
hello--world -> NO MATCH
hello-world-------this-is -> NO MATCH
-hello-world -> NO MATCH (leading dash)
hello-world- -> NO MATCH (trailing dash)
Here is what I have so far, but I dont know how to implement the "-" sign to test it if it is only once without repeating.
var regExp = /^[A-Za-z0-9-]+$/;
Try this:
/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$/
This will only match sequences of one or more sequences of alphanumeric characters separated by a single -. If you do not want to allow single words (e.g. just hello), replace the * multiplier with + to allow only one or more repetitions of the last group.
Here you go (this works).
var regExp = /^[A-Za-z0-9]+([-]{1}[A-Za-z0-9]+)+$/;
letters and numbers greedy, single dash, repeat this combination, end with letters and numbers.
(^-)|-{2,}|[^a-zA-Z-]|(-$) looks for invalid characters, so zero matches to that pattern would satisfy your requirement.
I'm not entirely sure if this works because I haven't done regex in awhile, but it sounds like you need the following:
/^[A-Za-z0-9]+(-[A-Za-z0-9]+)+$/
You're requirement is split up in the following:
One or more alphanumeric characters to start (that way you ALWAYS have an alphanumeric starting.
The second half entails a "-" followed by one or more alphanumeric characters (but this is optional, so the entire thing is required 0 or more times). That way you'll have 0 or more instances of the dash followed by 1+ alphanumeric.
I'm just not sure if I did the regex properly to follow that format.
The expression can be simplified to: /^[^\W_]+(?:-[^\W_]+)+$/
Explanation:
^ match the start of string
[^\W_]+ match one or more word(a-zA-Z0-9) chars
(?:-[^\W_]+)+ match one or more group of '-' follwed by word chars
$ match the end of string
Test: https://regex101.com/r/MODQxw/1