Swift Regex to check if String is Amount format (2x, 3x,...) - ios

I would like to check if a given String is in a amount format. A few examples for a better understanding:
Should return true:
2x
31x
3x abcd
Should return false:
2x3
3xabc
asdf3x
So in general: it has to start with a number (0-9), can be more digits. Right after the number a "x"/"X" should follow and after the "x"/"X" should be the end or a white space.
I am struggling to get this done.. This is what I tried:
func isAmountFormat() -> Bool {
return self.matches("[0-9]+[X,x]")
}
Can anyone help me out here?

You may use
"(?i)\\b[1-9][0-9]*x\\b"
See the regex demo. Details:
(?i) - case insensitive flag (in case you cannot pass the .caseInsensitive in your current regex matching method)
\b - a word boundary
[1-9] - a non-zero digit
[0-9]* - any zero or more digits
x - an X or x
\b - a word boundary.
See a Swift snippet:
let test = "3x abcd"
if test.range(of: "\\b[1-9][0-9]*x\\b", options: [.regularExpression, .caseInsensitive]) != nil {
print("Matched")
} else {
print("No match")
}
Note that if the match should occur at the start of the string, you may compile the regex object with the .anchored option, or replace the first \\b with ^.

Related

Checking if a string contains any special characters in swift while allowing all languages

I saw a similar post to this but none of the answers there helped me. I am looking to check if a string does not contain any special characters using swift regular expressions. I want to allow other iPhone keyboard letters though like Chinese, Hindi, Arabic, Korean, etc.. I only do not want to allow special characters like +, &, #, $, % though.
I have tried using:
func usernameTest(testStr:String) -> Bool {
return testStr.range(of: "^[ !\"#$%&'()*+,-./:;<=>?#\\[\\\\\\]^_`{|}~]+", options: .regularExpression) != nil
}
This did not work though. I thought it would check to see if any special characters were used, but when I tested phrases like "Tom###." and "%Will!!" it returned false. I would have expected this to return true since the strings that I passed in contained one or more of the special characters in the range.
Any help would be appreciated as we want our users to be able to create their usernames in any language but we still do not want to allow spaces or special characters.
you can try this way
var charSet = CharacterSet.init(charactersIn: "##$%+_)(")
var string2 = "test#3"
if let strvalue = string2.rangeOfCharacter(from: charSet)
{
print("true")
}
in the characterset init you can give the special characters which you want to check the occurance.
You must remove character "^" in the regex. So your function should look like this:
func usernameTest(testStr:String) -> Bool {
return testStr.range(of: "[ !\"#$%&'()*+,-./:;<=>?#\\[\\\\\\]^_`{|}~]+", options: .regularExpression) != nil }
func usernameTest(testStr:String) -> Bool {
let letters = CharacterSet.punctuationCharacters
let range = testStr.rangeOfCharacter(from: letters)
// range will be nil if no letters is found
if range != nil {
return true
}
else {
return false
}
}
try this one

How to validate a name(John D'Largy) in iOS Swift4.2?

i tried all possibilities in stack-overflow (link1, link2) answers no use for me.
I am using following Regex to validate a first name. In online case (OnlineRegex) it is working fine but when i implemented in mobile it is not working.
Please help me
func isValidName() -> Bool {
let RegEx = "^[a-zA-Z]+(([\\'\\,\\.\\-\\ ][a-zA-Z ])?[a-zA-Z]*)*$"
let Test = NSPredicate(format:"SELF MATCHES %#", RegEx)
return Test.evaluate(with: self)
}
i am calling above function as
let str = "John D'Largy"
if str.isValidName(){
print("Valid")
}else{ print("Not valid")}
Output : "Valid"
Same function i am calling to validate my first text feild i am getting "Not valid"
if firstNameTxt.text.isValidName(){
print("Valid")
}else{ print("Not valid")}
i entered same text in mobile keyword
OutPut: "Not valid"
Did i missing something? or Should i have to change regex value?.
Any suggestions.
Thanks in Advance.
You may use
(?:[a-zA-Z]+(?:['‘’,.\\s-]?[a-zA-Z]+)*)?
The code you have already requires the full string match and you need no explicit anchors like ^ / \A and $ / \z.
Also, since the single quotation marks are automatically converted to curly quotes, you should either add them to the regex or turn off the behavior.
One of the most important things about thi regex is that it should be able to match partially correct string, thus all of the parts are optional (i.e. they can match 0 chars). It is wrapped with an optional non-capturing group ((?:...)?) that matches 1 or 0 occurrences.
Regex details
[a-zA-Z]+ - 1 or more letters
(?: - start of the inner non-capturing group:
['‘’,.\\s-]? - 1 or 0 whitespaces, single quotes, hyphens
[a-zA-Z]+ - 1+ letters
)* - 0 or more repetitions.
Note: to match any Unbicode letter, use \\p{L} instead of [a-zA-Z].
Graph:
See, I tried your code in the playground and changed the syntax a bit but not the logic
Below is the code snippet, try running that in your playground
func isValidName(str: String) -> Bool {
let RegEx = "^[a-zA-Z]+(([\\'\\,\\.\\-\\ ][a-zA-Z ])?[a-zA-Z]*)*$"
let Test = NSPredicate(format:"SELF MATCHES %#", RegEx)
return Test.evaluate(with: str)
}
func check(){
let str = "John D'Largy"
if isValidName(str: str){
print("Valid")
}else{
print("Not valid")
}
}
check()
Hope it helps!

Understanding function with string validation

Consider following:
extension String {
func isValidEmail() -> Bool {
let characterset = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
print(characterset)
if self.rangeOfCharacter(from: characterset.inverted) != nil {
return false
} else {
return true
}
}
}
var name = "Login"
name.isValidEmail() // print true
var incorretLogin = "Loginъ"
incorretLogin.isValidEmail() // print false
Yes, function is work. But im in confussion - how its work?
If i understand correct it work like that:
it take set of characters, then check if all of tested string characters contain symbols from set, and if it is not, then it return false.
Ok, but what is inverted for? If i remove inverted, result will be wrong:
var name = "Login"
name.isValidEmail() // false
var incorretLogin = "Logъin"
incorretLogin.isValidEmail() // false
Now i understand nothing.
If function check simply if string letters are from character set, then why is it matter if set inverted or not?
Could someone explain?
I play a bit in playground:
let characterset = CharacterSet(charactersIn: "a")
print(characterset)
print(characterset.inverted)
Print same result:
<CFCharacterSet Items(U+0061)>
<CFCharacterSet Items(U+0061)>
inverted "returns an inverted copy of the receiver." (see https://developer.apple.com/documentation/foundation/characterset).
In your case inverted means all the characters except the ones you provide in the initializer (all characters except letters and digits). So the method returns false if the email string contains any character that is not a letter or a digit.
Playground example:
According to the documentation
rangeOfCharacter(from:)
Finds and returns the range in the receiver of the first character from a given character set.
The receiver is the string being checked. When no character from the set is found in the string, nil is returned.
When the set is inverted, it contains all invalid characters. Hence, rangeOfCharacter(from:) returns the location of the first invalid character. That is why your first approach works.
When you remove inverted, the call returns the location of the first valid character. Since "Logъin" has both valid and invalid characters, both calls return false. If you call your second function on a string consisting entirely of invalid characters, e.g. "Логин", you would get true.
Note that you can simplify the implementation by removing if:
let characterset = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
return self.rangeOfCharacter(from: characterset.inverted) == nil

How to implement a regex for password validation in Swift?

I want to implement a regex validaton for passwords in Swift? I have tried the following regex, but not successful
([(0-9)(A-Z)(!##$%ˆ&*+-=<>)]+)([a-z]*){6,15}
My requirement is as follows: Password must be more than 6 characters, with at least one capital, numeric or special character
You can use Regex for check your password strength
^(?=.*[A-Z].*[A-Z])(?=.*[!##$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$
Regex Explanation : -
^ Start anchor
(?=.*[A-Z].*[A-Z]) Ensure string has two uppercase letters.
(?=.*[!##$&*]) Ensure string has one special case letter.
(?=.*[0-9].*[0-9]) Ensure string has two digits.
(?=.*[a-z].*[a-z].*[a-z]) Ensure string has three lowercase letters.
.{8} Ensure string is of length 8.
$ End anchor.
Source - Rublar Link
try with this one for Password must be more than 6 characters, with at least one capital, numeric or special character
^.*(?=.{6,})(?=.*[A-Z])(?=.*[a-zA-Z])(?=.*\\d)|(?=.*[!#$%&? "]).*$
^ assert position at start of the string
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
(?=.{6,}) Positive Lookahead - Assert that the regex below can be matched
.{6,} matches any character (except newline)
Quantifier: {6,} Between 6 and unlimited times, as many times as possible, giving back as needed [greedy]
(?=.*[A-Z]) Positive Lookahead - Assert that the regex below can be matched
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
[A-Z] match a single character present in the list below
A-Z a single character in the range between A and Z (case sensitive)
(?=.*[a-zA-Z]) Positive Lookahead - Assert that the regex below can be matched
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
[a-zA-Z] match a single character present in the list below
a-z a single character in the range between a and z (case sensitive)
A-Z a single character in the range between A and Z (case sensitive)
(?=.*\\d) Positive Lookahead - Assert that the regex below can be matched
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
\d match a digit [0-9]
2nd Alternative: (?=.*[!#$%&? "]).*$
(?=.*[!#$%&? "]) Positive Lookahead - Assert that the regex below can be matched
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
[!#$%&? "] match a single character present in the list below
!#$%&? " a single character in the list !#$%&? " literally (case sensitive)
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
$ assert position at end of the string
https://regex101.com/#javascript
more this you can try ....
Minimum 8 characters at least 1 Alphabet and 1 Number:
"^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$"
Minimum 8 characters at least 1 Alphabet, 1 Number and 1 Special Character:
"^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$#$!%*#?&])[A-Za-z\\d$#$!%*#?&]{8,}$"
Minimum 8 characters at least 1 Uppercase Alphabet, 1 Lowercase Alphabet and 1 Number:
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$"
Minimum 8 characters at least 1 Uppercase Alphabet, 1 Lowercase Alphabet, 1 Number and 1 Special Character:
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[d$#$!%*?&#])[A-Za-z\\dd$#$!%*?&#]{8,}"
Minimum 8 and Maximum 10 characters at least 1 Uppercase Alphabet, 1 Lowercase Alphabet, 1 Number and 1 Special Character:
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$#$!%*?&#])[A-Za-z\\d$#$!%*?&#]{8,10}"
public func isValidPassword() -> Bool {
let passwordRegex = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z!##$%^&*()\\-_=+{}|?>.<,:;~`’]{8,}$"
return NSPredicate(format: "SELF MATCHES %#", passwordRegex).evaluate(with: self)
}
If you need a quick fix. This is validation for a password with regex.
Copy/paste in helper or extension file and use it.
The regex is
(?:(?:(?=.*?[0-9])(?=.*?[-!##$%&*ˆ+=_])|(?:(?=.*?[0-9])|(?=.*?[A-Z])|(?=.*?[-!##$%&*ˆ+=_])))|(?=.*?[a-z])(?=.*?[0-9])(?=.*?[-!##$%&*ˆ+=_]))[A-Za-z0-9-!##$%&*ˆ+=_]{6,15}
func isValidPassword() -> Bool {
// least one uppercase,
// least one digit
// least one lowercase
// least one symbol
// min 8 characters total
let password = self.trimmingCharacters(in: CharacterSet.whitespaces)
let passwordRegx = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&<>*~:`-]).{8,}$"
let passwordCheck = NSPredicate(format: "SELF MATCHES %#",passwordRegx)
return passwordCheck.evaluate(with: password)
}
for which missing validation:
func getMissingValidation(str: String) -> [String] {
var errors: [String] = []
if(!NSPredicate(format:"SELF MATCHES %#", ".*[A-Z]+.*").evaluate(with: str)){
errors.append("least one uppercase")
}
if(!NSPredicate(format:"SELF MATCHES %#", ".*[0-9]+.*").evaluate(with: str)){
errors.append("least one digit")
}
if(!NSPredicate(format:"SELF MATCHES %#", ".*[!&^%$##()/]+.*").evaluate(with: str)){
errors.append("least one symbol")
}
if(!NSPredicate(format:"SELF MATCHES %#", ".*[a-z]+.*").evaluate(with: str)){
errors.append("least one lowercase")
}
if(str.count < 8){
errors.append("min 8 characters total")
}
return errors
}
func validpassword(mypassword : String) -> Bool
{
let passwordreg = ("(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z])(?=.*[##$%^&*]).{8,}")
let passwordtesting = NSPredicate(format: "SELF MATCHES %#", passwordreg)
return passwordtesting.evaluate(with: mypassword)
}
#IBOutlet weak var password_textfield: UITextField! //create a Password text field IBOutlet
#IBAction func login_btton(_ sender: UIButton) { //Click & Call to Login Button
let password = validpassword(mypassword: password_textfield.text!) //get text Field data & checked through the function
if(password == false)
{
print("Valid Password") //Use to Alert Msg Box
}
else
{
print("Login Safe") //Use to Alert Msg Box
}
}
## Function Use to validation is password and confirm password is same, Password must have more then some characters , Password contain some special character , Password must one digit , Password must one uppercase letter ##

How modify the word boundary that includes '-' as a word character

I'd like to capture a passcode that is between 6 and 8 digits long.
I'd like to match:
123-4567 and
12-34-56-78
And fail:
1234567890 and 123-456-7890
As it stands I'm using (\\b(?:\\d[-,\\h]?+){5,7}\\d\\b)
This successfully knocks back 1234567890, but gives a partial match on 123-456-7890. Is there a way for the word boundary to include hyphens within it's count?
You can use lookarounds:
(?<!-)\b\d(?:[-,\h]?\d){5,7}(?!-)\b
See the regex demo
Swift regex uses ICU flavor, so both the lookbehind and a lookahead will work. The (?<!-) lookbehind makes sure there is no - before the digit that starts a new word (or after a word boundary), and (?!-) lookahead makes sure there is no - after the 8th digit right at the word boundary.
Do not forget to use double backslashes.
As #AlanMoore suggests, the word boundaries and --lookarounds can be substituted with lookarounds (?<![\w-]) and (?![\w-]). This will make the regex a bit more efficient since there will be only one position to be checked once at the start and end:
(?<![\w-])\d(?:[-,\h]?\d){5,7}(?![\w-])
See another demo
Not an exact literal answer, but an alternative native Swift solution
enum CheckResult {
case Success(String), Failure
}
func checkPassCode(string : String) -> CheckResult
{
let filteredArray = string.characters.filter{ $0 != "-" }.map{ String($0) }
return (6...8).contains(filteredArray.count) ? .Success(filteredArray.joinWithSeparator("")) : .Failure
}
checkPassCode("123-4567") // Success(1234567)
checkPassCode("12-34-56-78") // Success(12345678)
checkPassCode("1234567890") // Failure
checkPassCode("123-456-7890") // Failure

Resources