NSPredicate with regEx, returns wrong result [duplicate] - swift

This question already has an answer here:
regex in swift is not working with this example?
(1 answer)
Closed 4 years ago.
I wrote the following regular expression to validate usernames:
/^[a-zA-Z0-9\\._]+$/
However, when I try to use it, something messes up, since it gives me the wrong result. The input I tried is the same as my SO handle: ilikecode. This is how I apply the regex:
let regex = "/^[a-zA-Z0-9\\._]+$/"
let usernameTest = NSPredicate(format: "SELF MATCHES %#", regex)
print("username is valid", usernameTest.evaluate(with: username), username)
However, the regex always returns false.
Does anybody know how this is possible?
Thanks!

In some languages /.../ is used to delimit a regular expression
pattern, separating the pattern from an action and the options,
for example
if ($userName =~ m/^[a-zA-Z0-9\\._]+$/i)
in Perl. But NSPredicate (or NSRegularExpression) take just a pattern
as argument, without enclosing slashes.
Also the anchors are implicit for the MATCHES operator, and
the [c] option can be used to specify case-insensitive matching:
let regex = "[a-z0-9\\._]+"
let usernameTest = NSPredicate(format: "SELF MATCHES[c] %#", regex)

Related

Count leading tabs in Swift string

I need to count the number of leading tabs in a Swift string. I know there are fairly simple solutions (e.g. looping over the string until a non-tab character is encountered) but I am looking for a more elegant solution.
I have attempted to use a regex such as ^\\t* along with the .numberOfMatches method but this detects all the tab characters as one match. For example, if the string has three leading tabs then that method just returns 1. Is there a way to write a regex that treats each individual tab character as a single match?
Also open to other ways of approaching this without using a regex.
Here is a non-regex solution
let count = someString.prefix(while: {$0 == "\t"}).count
You may use
\G\t
See the regex demo.
Here,
\G - matches a string start position or end of the previous match position, and
\t - matches a single tab.
Swift test:
let string = "\t\t123"
let regex = try! NSRegularExpression(pattern: "\\G\t", options: [])
let numberOfOccurrences = regex.numberOfMatches(in: string, range: NSRange(string.startIndex..., in: string))
print(numberOfOccurrences) // => 2

Parsing Infix Mathematical Expressions in Swift Using Regular Expressions

I would like to convert a string that is formatted as an infix mathematical to an array of tokens, using regular expressions. I'm very new to regular expressions, so forgive me if the answer to this question turns out to be too trivial
For example:
"31+2--3*43.8/1%(1*2)" -> ["31", "+", "2", "-", "-3", "*", "43.8", "/", "1", "%", "(", "*", "2", ")"]
I've already implemented a method that achieves this task, however, it consists of many lines of code and a few nested loops. I figured that when I define more operators/functions that may even consist of multiple characters, such as log or cos, it would be easier to edit a regex string rather than adding many more lines of code to my working function. Are regular expressions the right job for this, and if so, where am I going wrong? Or am I better off adding to my working parser?
I've already referred to the following SO posts:
How to split a string, but also keep the delimiters?
This one was very helpful, but I don't believe I'm using 'lookahead' correctly.
Validate mathematical expressions using regular expression?
The solution to the question above doesn't convert the string into an array of tokens. Rather, it checks to see if the given string is a valid mathematical expression.
My code is as follows:
func convertToInfixTokens(expression: String) -> [String]?
{
do
{
let pattern = "^(((?=[+-/*]))(-)?\\d+(\\.\\d+)?)*"
let regex = try NSRegularExpression(pattern: pattern)
let results = regex.matches(in: expression, range: NSRange(expression.startIndex..., in: expression))
return results.map
{
String(expression[Range($0.range, in: expression)!])
}
}
catch
{
return nil
}
}
When I do pass a valid infix expression to this function, it returns nil. Where am I going wrong with my regex string?
NOTE: I haven't even gotten to the point of trying to parse parentheses as individual tokens. I'm still figuring out why it won't work on this expression:
"-99+44+2+-3/3.2-6"
Any feedback is appreciated, thanks!
Your pattern does not work because it only matches text at the start of the string (see ^ anchor), then the (?=[+-/*]) positive lookahead requires the first char to be an operator from the specified set but the only operator that you consume is an optional -. So, when * tries to match the enclosed pattern sequence the second time with -99+44+2+-3/3.2-6, it sees +44 and -?\d fails to match it (as it does not know how to match + with -?).
Here is how your regex matches the string:
You may tokenize the expression using
let pattern = "(?<!\\d)-?\\d+(?:\\.\\d+)?|[-+*/%()]"
See the regex demo
Details
(?<!\d) - there should be no digit immediately to the left of the current position
-? - an optional -
\d+ - 1 or more digits
(?:\.\d+)? - an optional sequence of . and 1+ digits
| - or
\D - any char but a digit.
Output using your function:
Optional(["31", "+", "2", "-", "-3", "*", "43.8", "/", "1", "%", "(", "1", "*", "2", ")"])

Match "com.project.name" but not when it contains something else

I have the following code:
var i = "test"
and
var i = "com.project.name.test"
print("something else")
fatalError("some error")
I have a regex:
"((?!com\.project\.name).)*"
to match any string that does NOT contain "com.project.name".
However, I want to modify it to still have the above condition but not if the line contains print\(.*?\) and fatalError\(.*?\).
Why do I want to do this? Because I can only use regex for SwiftLint custom rules and right now my regex is greedy and matches every single string in the project that the developers forgot to localize..
What I've tried:
"((?!com\\.project\\.name).)*(?!print)(?!fatalError)"
but it does not work and instead matches the same as the original expression.
You may use this regex with a negative lookahead assertions:
^(?!.*(?:com\.project\.name|print\(|fatalError\()).*
RegEx Demo
This negative lookahead assertion uses alternations to fail the match on 3 different matches anywhere in the input:
com\.project\.name
print\(
fatalError\(

swift Using predicate

request.predicate=NSPredicate( format:"lnameID= \(light.valueForKey("lnameID"))",nil);
When using the request.predicate in Swift,it goes wrong.
How to solve the problem in the format " xx "xx" xx" ?
You should not use string interpolation when building predicates. This will give wrong
results or crash at runtime as soon as there are any special characters (like
single or double quotes) in the values.
Better use the %# placeholder, for example:
let lnameID = light.valueForKey("lnameID") as String // assuming that it is a string
request.predicate = NSPredicate(format: "lnameID = %#", lnameID)
You can put escaped quotes around and the escaped variable within the string like so:
request.predicate=NSPredicate( format:"lnameID= \"\(light.valueForKey("lnameID"))\"",nil)
Or you can use a placeholder, %#, where quotes are generated, as seen in Martin R's answer. Using escaped quotes is the more native way to do it in swift.

Regular expression for numbers

I need a regular expression to detect at least one number in a string. Other characters can be anything. Please help me to implement this in objective C.
Regards,
Dilshan
\d+
Match one or more digit.
This is a very similar question to:
Regular Expressions in Objective-C and Core Data
Check ICU Regex Documentation for figuring out your regular expression needs
To match a digit anywhere in string use .*\\d.*. To implement in objective-c use NSPredicate try something like this:
NSString *matchphrase = #".*\\d.*";
BOOL match = NO;
NSString *item = #"string with d1g1it";
NSPredicate *matchPred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", matchphrase];
match = [matchPred evaluateWithObject:item];
More here
Edited according Dislhan comment.