VBScript Regular Expression - regex

Need help building a VBScript regex that checks for a valid computer name and returns only invalid characters. String can contain numbers, upper and lower case letters, and (-) sign only. It can't start or end with (-) and cannot be only numbers.
Valid (Returns no match):
computer
Computer8
8Computer
Com8puter
Com-Puter
Computer-123
Invalid (Returns a match to invalid characters):
123
-computer
computer-
com*puter
PC&123

According to this: http://msdn.microsoft.com/en-us/library/ms974570.aspx VBScript has its own regex syntactic flavour. Note that NetBIOS computer names have a length limit of 15.
Then it should be "^\w[\w-]{0,14}$"
That RegEx satisfies all of the requirements except the "is all numbers". That can be done by running a second regex "^\d+$".
In code:
Dim regexValid, regexNumber
Set regexValid = New RegExp
Set regexNumber = New RegExp
regexValid.Global = True
regexValid.IgnoreCase = True
regexNumber.Global = True
regexNumber.IgnoreCase = True
regexValid.Pattern = "^\w[\w\-]{0,14}$"
regexNumber.Pattern = "^\d+$"
Dim inputString
inputString = InputBox("Computer name?")
If regexValid.Test( inputString ) And Not regexNumber.Test( inputString ) Then
' It's a valid computer name string
Else
' It's invalid
End If
Hmm, this is the first VBScript I've written this year.

I ended up switching the valid and invalid returns. I also ended up using two different RegEx strings. The first is:
^[0-9a-zA-Z]{1,}[-]*[0-9a-zA-Z]{1,}$
This doesn't allow the (-) at the beginning or end and requires all numbers, letters, or (-). It also requires a string of at least two characters.
The second is:
"[a-zA-Z]"
This makes sure there is at least one letter included.

Something like this /^([0-9]|[a-zA-Z]){1,}[a-zA-Z0-9-]+([0-9]|[a-zA-Z]){1,}$/

Related

Excel VBA Regex Check For Repeated Strings

I have some user input that I want to validate for correctness. The user should input 1 or more sets of characters, separated by commas.
So these are valid input
COM1
COM1,COM2,1234
these are invalid
COM -- only 3 characters
COM1,123 -- one set is only 3 characters
COM1.1234,abcd -- a dot separator not comma
I googled for a regex pattern to this and found a possible pattern that tested for a recurring instance of any 3 characters, and I modified like so
/^(.{4,}).*\1$/
but this is not finding matches.
I can manage the last comma that may or may not be there before passing to the test so that it is always there.
Preferably, I would like to test for letters (any case) and numbers only, but I can live with any characters.
I know I could easily do this in straight VBA splitting the input on a comma delimiter and looping through each character of each array element, but regex seems more efficient, and I will have more cases than have slightly different patterns, so parameterising the regex for that would be better design.
TIA
I believe this does what you want:
^([A-Z|a-z|0-9]{4},)*[A-Z|a-z|0-9]{4}$
It's a line beginning followed by zero or more groups of four letters or numbers ending with a comma, followed by one group of four letters or number followed by an end-of-line.
You can play around with it here: https://regex101.com/r/Hdv65h/1
The regular expression
"^[\w]{4}(,[\w]{4})*$"
should work.
You can try this to see whether it works for all your cases using the following function. Assuming your test strings are in cells A1 thru A5 on the spreadsheet:
Sub findPattern()
Dim regEx As New RegExp
regEx.Global = True
regEx.IgnoreCase = True
regEx.Pattern = "^[\w]{4}(,[\w]{4})*$"
Dim i As Integer
Dim val As String
For i = 1 To 5:
val = Trim(Cells(i, 1).Value)
Set mat = regEx.Execute(val)
If mat.Count = 0 Then
MsgBox ("No match found for " & val)
Else
MsgBox ("Match found for " & val)
End If
Next
End Sub

VBA regexp pattern combining match and not matching a pattern

Trying to extract valid phone numbers from a string with no visible delimiters between different data types. In effect, the data around the potential phone number is random and irrelevant.
What should be matched. I am trying to match either one of the following:
[random garbage][optional '1'][optional '(']###[optional')'[[random or no white space]###-####[random garbage] or
[random garbage]###[optional '-']###,[optional '-']####[random garbage]
Only the 1st phone number is to be used, so I used Global = False in the code below. I could make it even more robust, but I've examined the data and this should be enough.
Working pattern.Here's a code snippet from a function (it returns the matching phone number) that contains the pattern that worked.
With regex
.Global = False
.Pattern = "1?(\(?\d{3}\)?\(s+)?|\d{3}-?)\d{3}-?\d{4}"
'this works but does detect an extension as explained above
End With
What should not be matched. I realized that I also need to search for an extension next to the phone number (i.e. [phone number][white space]x#) and if that exists, to treat the phone number as invalid (.test should evaluate to false).
Failed attemps. They all failed (even valid phone numbers had .test evaluate to false):
.Pattern = "1?(\(?\d{3}\)?\(s+)?|\d{3}-?)\d{3}-?\d{4}^(\s?x\d)"
'detect not([optional single white space]x#), added "^(\s?x\d)"
'or
.Pattern = "1?(\(?\d{3}\)?\(s+)?|\d{3}-?)\d{3}-?\d{4}^((\s+?)[x]\d)"
'detect not([optional multiple white space]x#), added "^((\s+?)[x]\d)"
Not sure how to combine positive match tests and negative (not) match tests in the same pattern.
Work-arounds I've tried. When I couldn't get it to work, I tried the following Like patterns (using VBA 'Like', prior to calling the function that utilized Regexp) and that also failed (all evaluated to false even with test strings that contained examples such as "...1x2" or "5 x33" or "...7 x444"; with patterns like "*#x#*", "*#{ x}#*", ""*#{ x}#*".
Here is the code snippet to test the Like function:
If Not (OrigNum Like "*#x#" Or OrigNum Like "*#[ x}#" Or OrigNum Like "*#[ x]#*") Then
Debug.Print "No #x# in string"
OrigNum = ExtractPhoneNumber(OrigNum)
Else
Debug.Print "#x# in string"
End If
Every string evaluated ended up causing "No x# in string" to be displayed (evaluated to false), even when the string contained the above examples, which should have evaluated to true and "#x# in string" being displayed.
Dazed and confused for so long it's...OK, enough of the Led Zepp reference :-)
Phone number:
[optional '1'][optional '(']###[optional')'[[random or no white space]###-####
###[optional '-']###[optional '-']####
*I removed a comma I assumed as a typo, and also assuming the leading 1 is optional for both cases from what I read from your patterns.
Don't match:
[phone number][white space]x#
What you're looking for is negative lookaheads.
(?! subexpression ) asserts for that subexpression from the current position and, if the subexpression matches, the match attempt fails (i.e. not followed by).
E.g. (?!\s*x\d) fails when the current position is followed by optional whitespace, an "x" and a digit.
Regex:
1?(?:\(\d{3}\)|\d{3}-?)\s*\d{3}-?\d{4}(?!\s*x\d)
Code:
Public Function getPhoneNumber(strInput As String) As Variant
Dim regex As New RegExp
Dim matches As Object
regex.Pattern = "1?(?:\(\d{3}\)\s*|\d{3}-?)\d{3}-?\d{4}(?!\s*x\d)"
regex.Global = False
Set matches = regex.Execute(strInput)
If matches.Count = 0 Then
getPhoneNumber = CVErr(xlErrNA)
Else
getPhoneNumber = matches(0).Value
End If
End Function
Results (🎵As it was, then again it will be; though the course may change sometimes🎵):

How to loop a regex.match or add a range to String.Contains()

I've built a password Generator:
Public Function PassGen()
Dim pool As String = "0123456789abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXYZ+#*#%&/()?!$-"
Dim rnd As New Random
Dim result As String
Dim i As Integer = 0
Do Until i = 10
result &= pool(rnd.Next(0, pool.Length))
i = i + 1
Loop
Return result
End Function
Now I'd like to check if the generated password contains a number, upper- and lowercase and special characters. If the generated password doesn't contain those 4 things, it should generate another password and check it again and so on.
I tried to loop a Regex.Match:
Dim text As String = PassGen()
Do Until Regex.Match(text, "^[0-9]$")
text = PassGen()
Loop
What didnt work as it wont let me loop a regex.match().
I also tried it with String.Contains(). But as far as I know the Contains-method can only check for one string and not for a range or a type(like Integer).
Is there a possibility to check my password for those four string-ranges or do I have to modify my function that it has to use one of each?
You could use the LIKE keyword in VB. The LIKE is like a mini-regex built in into VB.NET.
If text Like "*[A-Z]*" AndAlso text Like "*[a-z]*" AndAlso text Like "*[0-9]*" AndAlso text Like "*[+#*#%&/()?!$-]*" Then
' it is a valid password
Else
' password doesn't match required constraints... do whatever to regenerate it here...
End If
You can use one regex to check the password strength:
Do Until System.Text.RegularExpressions.Regex.IsMatch(text, "(?s)^(?=.*\d)(?=.*\p{Ll})(?=.*\p{Lu})(?=.*\W)")
The \W matches all special characters other than letters, digits and _, thus you have a much wider scope with it than manually defining a character class like [+#*#%&/()?!$-].
The (?s) is an inline singleline modifier to force . to match a newline, too. The \d matches a digit, the \p{Ll} matches a lowercase letter, and \p{Lu} matches an uppercase letter. The lookaheads (?=...) are executed one after another upon success. If one of them returns false, the whole match is failed.

Check if string is uppercase and numbers

I want to check if a string contains only uppercase letters and numbers. I have attempted to solve this using RegExp and what I have so far is:
Function CheckForInvalidChars()
dim b
Set re = New RegExp
re.Pattern = "[A-Z_0-9]"
b = re.Test("eS")
msgbox b
End Function
However the variable "b" returns true since I guess it finds a match in the "S" although I want that particular string to return false since not all letters are uppercase. How would I go about achieving this?
I have tried to do this with functions as well using IsNumeric but can't find a IsUpperCase.
Generally speaking, if you want to match whole string using regex, you will usually end up using ^ and $ to describe the start and end of string.
Also, just [A-Z_0-9] matches a single character.
Assuming you don't allow whitespaces, ^[A-Z_0-9]*$ would be the regex you're looking for.
If UCase(s) <> s then there is at least one lower case letter in the string s.
I'd recommend to just UCase the string if you want to enforce uppercase letters. Then you can simplify the check to this:
Function CheckForInvalidChars(s)
Set re = New RegExp
re.Pattern = "^\w+$"
CheckForInvalidChars = re.Test(s)
End Function
teststring = InputBox("Input something")
teststring = UCase(teststring)
WScript.Echo "" & CheckForInvalidChars(teststring)
The escape sequence \w matches word characters, i.e. uppercase letters, lowercase letters (ruled out due to the prior UCase), digits, and underscores. The + rules out empty strings by requiring at least one word character.
#Andris is right, correct the regular expression as follows:
Function CheckForInvalidChars()
dim b
Set re = New RegExp
re.Pattern = "^[A-Z_0-9]*$"
b = re.Test("eS")
msgbox b
End Function

Textbox that accepts all the characters but returns only numbers

I need the code to filter the data entered in a textbox. Although it accepts all the characters during runtime, the code should remove all the strings and alpha numeric characters except the numbers (which would be my output). I tried the following code but guess it won't do:
a = Textbox1.text
Dim value As Decimal = CDec(Regex.Replace(a, "[\D]", ""))
Your regex was correct (just a bit redundant, \D would have done). Better would have been \D+ so consecutive non-decimals are replaced at once.
ResultString = Regex.Replace(SubjectString, "\D+", "")
I use this jQuery plugin. http://plugins.jquery.com/project/jQueryNumberLettersPlugin
$("#id").numbers();
That would only allow numbers to be entered into the selected input.
Try this instead, use the matching object
Dim a As String
Try
a = Regex.Match(Textbox1.text, "\d+").Value
Catch ex As ArgumentException
'Syntax error in the regular expression
End Try