regex - don't allow name to finish with hyphen - javascript

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.

Related

Block a comma using regular expressions in multiline text

I have a specific validation scenario that I am trying to solve using regexp pattern in JavaScript. I am struggling to write a suitable regular expression.
The rule is that validation must fail if a comma appears anywhere within a multiline piece of text that is enterred by the user into a text area, but only if it appears BEFORE a pipe character on the same line. It is assumed that every line will contain a pipe character somewhere (this is enforced elsewhere).
Examples below should clarify the requirement:
Example 1 - PASS: No commas
one|One
two|Two
three|Three
Example 2 - PASS:
Comma appears, but after pipe character and so is ok
one|One
two|Tw,o
three|Three
Example 3 - FAIL: Comma appears before pipe character
o,ne|One
two|Two
three|Three
Example 4 - FAIL: Comma appears before pipe character
one|One
two,|Two
three|Three
The closest attempt I have got so far is:
/^[^,]+$/g
However, this doesn't take into account that a comma after the pipe character is permitted.
One approach could be using a negative lookahead to assert that the line does not contain a pipe after a comma.
^(?![^,\r\n]*,[^\r\n|]*\|).*(?:\r?\n(?![^,\r\n]*,[^\r\n|]*\|).*)*$
In parts
^ Start of the string
(?![^,\r\n]*,[^\r\n|]*\|) Assert not a comma before a pipe char
.* Match the whole line
(?: Non capture group
\r?\n match a newline
(?![^,\r\n]*,[^\r\n|]*\|) Assert not a comma before a pipe char
.* Match the whole line
)* Close the group and repeat 0+ times to optionally match all the following lines
$ End of string.
Regex demo no match | Regex demo match
As per my comment: If you could negate the logic and react to not matching a bad pattern (!badPattern.test(str)), the whole thing becomes a lot easier.
For example:
const cases = [
// good
`one|One
two|Two
three|Three`,
// good
`one|One
two|T,wo
three|Three`,
// bad
`one|One
two,|Two
three|Three`,
];
const badPattern = /,.*\|/;
const out = cases.map(val => ({
input: val,
result: !badPattern.test(val) ? 'good' : 'bad',
}))
console.log(out);

regex to coordinates WGS84?

I'm trying this regular expressión, but I can't validate correctly the end white space and the letter:
/^\d{0,2}(\-\d{0,2})?(\-\d{0,2})?(\ ?\d[W,E]?)?$/
Examples of correct values:
33-39-10 N //OK
85-50 W //OK
-85-50 E //Wrong
What's wrong?
\d{0,2} this quantifier also matches a digit zero times so that would match the leading - in the 3rd example.
In the character class [W,E] you could omit the comma and list the characters you allow to match [ENW]
If only the third group is optional you could try including the whitespace before the end of the line $
^\d{2}(-\d{2})(-\d{2})? [ENW] $
I have used this regular expression : ^(?!\-)\d{0,2}?(\-\d{0,2}).+\s(N|E|W|S)$
Using a negative lookahead, we have excluded anything that starts with a dash (-).
(?!\-) = Starting at the current position in the expression,
ensures that the given pattern will not match
\s(N|E|W|S) matches anything with a space (\s) and one of the letters using OR operator |.
You may also use \s+(N|E|W|S).
+ = Matches between one and unlimited times, as many times as
possible, giving back as needed

JQuery match with RegEx not working

I have a filename that will be something along the lines of this:
Annual-GDS-Valuation-30th-Dec-2016-082564K.docx
It will contain 5 numbers followed by a single letter, but it may be in a different position in the file name. The leading zero may or may not be there, but it is not required.
This is the code I come up with after checking examples, however SelectedFileClientID is always null
var SelectedFileClientID = files.match(/^d{5}\[a-zA-Z]{1}$/);
I'm not sure what is it I am doing wrong.
Edit:
The 0 has nothing to do with the code I am trying to extract. It may or may not be there, and it could even be a completely different character, or more than one, but has nothing to do with it at all. The client has decided they want to put additional characters there.
There are at least 3 issues with your regex: 1) the pattern is enclosed with anchors, and thus requires a full string match, 2) the d matches a letter d, not a digit, you need \d to match a digit, 3) a \[ matches a literal [, so the character class is ruined.
Use
/\d{5}[a-zA-Z]/
Details:
\d{5} - 5 digits
[a-zA-Z] - an ASCII letter
JS demo:
var s = 'Annual-GDS-Valuation-30th-Dec-2016-082564K.docx';
var m = s.match(/\d{5}[a-zA-Z]/);
console.log(m[0]);
All right, there are a few things wrong...
var matches = files.match(/\-0?(\d{5}[a-zA-Z])\.[a-z]{3,}$/);
var SelectedFileClientID = matches ? matches[1] : '';
So:
First, I get the matches on your string -- .match()
Then, your file name will not start with the digits - so drop the ^
You had forgotten the backslash for digits: \d
Do not backslash your square bracket - it's here used as a regular expression token
no need for the {1} for your letters: the square bracket content is enough as it will match one, and only one letter.
Hope this helps!
Try this pattern , \d{5}[a-zA-Z]
Try - 0?\d{5}[azA-Z]
As you mentioned 0 may or may not be there. so 0? will take that into account.
Alternatively it can be done like this. which can match any random character.
(\w+|\W+|\d+)?\d{5}[azA-Z]

Javascript regex to get substring, excluding a pattern?

I am still a beginner :)
I need to get a substring ignoring the last section inside [] (including the brackets []), i.e. ignore the [something inside] section in the end.
Note - There could be other single occurances of [ in the string. And they should appear in the result.
Example
Input of the form -
1 checked arranged [1678]
Desired output -
1 checked arranged
I tried with this
var item = "1 checked arranged [1678]";
var parsed = item.match(/([a-zA-Z0-9\s]+)([(\[d+\])]+)$/);
|<-section 1 ->|<-section 2->|
alert(parsed);
I tried to mean the following -
section 1 - multiple occurrences of words (containing literals and nos.) followed by spaces
section 2 - ignore the pattern [something] in the end.
But I am getting 1678],1678,] and I am not sure which way it is going.
Thanks
OK here is the problem in your expression
([a-zA-Z0-9\s]+)([(\[d+\])]+)$
The Problem is only in the last part
([(\[d+\])]+)$
^ ^
here are you creating a character class,
what you don't want because everything inside will be matched literally.
((\[d+\])+)$
^ ^^
here you create a capturing group and repeat this at least once ==> not needed
(\[d+\])$
^
here you want to match digits but forgot to escape
That brings us to
([a-zA-Z0-9\s]+)(\[\d+\])$
See it here on Regexr, the complete string is matched, the section 1 in capturing group 1 and section 2 in group 2.
When you now replace the whole thing with the content of group 1 you are done.
You could do this
var s = "1 checked arranged [1678]";
var a = s.indexOf('[');
var b = s.substring(0,a);
alert(b);
http://jsfiddle.net/jasongennaro/ZQe6Y/1/
This s.indexOf('['); checks for where the first [ appears in the string.
This s.substring(0,a); chops the string, from the beginning to the first [.
Of course, this assumes the string is always in a similar format
var item = '1 check arranged [1678]',
matches = item.match(/(.*)(?=\[\d+\])/));
alert(matches[1]);
The regular expression I used makes use of a positive lookahead to exclude the undesired portion of the string. The bracketed number must be a part of the string for the match to succeed, but it will not be returned in the results.
Here you can find how to delete stuff inside square brackets. This will leave you with the rest. :)
Regex: delete contents of square brackets
try this if you only want to get rid of that [] in the end
var parsed = item.replace(/\s*\[[^\]]*\]$/,"")
var item = "1 checked arranged [1678]";
var parsed = item.replace(/\s\[.*/,"");
alert(parsed);
That work as desired?
Use escaped brackets and non-capturing parentheses:
var item = "1 checked arranged [1678]";
var parsed = item.match(/([\w\s]+)(?:\s+\[\d+\])$/);
alert(parsed[1]); //"1 checked arranged"
Explanation of regex:
([\w\s]+) //Match alphanumeric characters and spaces
(?: //Start of non-capturing parentheses
\s* //Match leading whitespace if present, and remove it
\[ //Bracket literal
\d+ //One or more digits
\] //Bracket literal
) //End of non-capturing parentheses
$ //End of string

validating variable in javascript

Hi i have a field in php that will be validated in javascript using i.e for emails
var emailRegex = /^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$/;
What i'm after is a validation check which will look for the
first letter as a capital Q
then the next letters can be numbers only
then followed by a .
then two numbers only
and then an optional letter
i.e Q100.11 or Q100.11a
I must admit i look at the above email validation check and i have no clue how it works but it does ;)
many thanks for any help on this
Steve
The ^ marks the beginning of the string, $ matches the end of the string. In other words, the whole string should exactly match this regular expression.
[\w-\.]+: I think you wanted to match letters, digits, dots and - only. In that case, the - should be escaped (\-): [\w\-\.]+. The plus-sign makes is match one or more times.
#: a literal # match
([\w-]+\.)+ letters, digits and - are allowed one or more times, with a dot after it (between the parentheses). This may occur several times (at least once).
[\w-]{2,4}: this should match the TLD, like com, net or org. Because a TLD can only contain letters, it should be replaced by [a-z]{2,4}. This means: lowercase letters may occur two till four times. Note that the TLD can be longer than 4 characters.
An regular expression which should follow the next rules:
a capital Q (Q)
followed by one or more occurrences of digits (\d+)
a literal dot (.)
two digits (\d{2})
one optional letter ([a-z]?)
Result:
var regex = /Q\d+\.\d{2}[a-z]?/;
If you need to match strings case-insensitive, add the i (case-insensitive) modifier:
var regex = /Q\d+\.\d{2}[a-z]?/i;
Validating a string using a regexp can be done in several ways, one of them:
if (regex.test(str)) {
// success
} else {
// no match
}
var emailRegex = /^Q\d+\.\d{2}[a-zA-Z]?#([\w-]+\.)+[a-zA-Z]+$/;
var str = "Q100.11#test.com";
alert(emailRegex.test(str));
var regex = /^Q[0-9]+\.[0-9]{2}[a-z]?$/;
+ means one or more
the period must be escaped - \.
[0-9]{2} means 2 digits, same as \d{2}
[a-z]? means 0 or 1 letter
You can check your regex at http://regexpal.com/

Categories