Create an NSPredicate with a line break as part of a string - swift

I need to create a predicate that will look for the following string:
"fred\n5" where \n is a newline.
At least, this is string that is returned when reading the metadata back

You can do it with Regular Expression
let string = """
fred
5
"""
let predicate = NSPredicate(format: "self MATCHES %#", "fred\\n5")
predicate.evaluate(with: string) // true
It's also possible to use the pattern fred(\\n|\\r)5, it considers both linefeed and return.
Alternatively remove the newline character (actually any whitespace and newline characters)
let trimmedString = string.replacingOccurrences(of: "\\s", with: "", options: .regularExpression)

Related

Swift Regex: Remove numbers embedded inside words in a String

Goal: Remove numbers embedded inside a string.
Example: let testString = "5What's9 wi3th this pro9ject I'm try905ing to build."
Desired Output: testString = "5What's9 with this project I'm trying to build"
What I've Tried:
let resultString = testString
.replacingOccurrences(of: "\\b[:digit:]\\b", with: "", options: .regularExpression)
// fails, returns string as is
let resultString = testString
.replacingOccurrences(of: "(\\d+)", with: "", options: .regularExpression)
// fails, returns all numbers removed from string.. close
let resultString = testString
.replacingOccurrences(of: "[0-9]", with: "", options: .regularExpression)
// removes all numbers from string.. close
How can we remove numbers that are inside of words only?
We can try doing a regex replacement on the following pattern:
(?<=\S)\d+(?=\S)
This matches only numbers surrounded on both sides by non whitespace characters. Updated code:
let resultString = testString
.replacingOccurrences(of: "(?<=\\S)\\d+(?=\\S)", with: "", options: .regularExpression)

break line regex

How can I match a break line from OCR text using regex?
For example I have this text:
"NAME JESUS LASTNAME"
I want to find a match with NAME and then get the next two lines
if (line.text.range(of: "^NAME+\\n", options: .regularExpression) != nil){
let name = line.text
print(name)
}
You can use a positive look behind to find NAME followed by a new line, and try to match a line followed by any text that ends on a new line or the end of a string "(?s)(?<=NAME\n).*\n.*(?=$|\n)":
For more info about the regex above you can check this
Playground testing:
let str = "NAME\nJESUS\nLASTNAME"
let pattern = "(?s)(?<=NAME\n).*\n.*(?=$|\n)"
if let range = str.range(of: pattern, options: .regularExpression) {
let text = String(str[range])
print(text)
}
This will print
JESUS
LASTNAME
You can use
(?m)(?<=^NAME\n).*\n.*
See the regex demo. Details:
(?m) - a multiline option making ^ match start of a line
(?<=^NAME\n) - a positive lookbehind that matches a location that is immediately preceeded with start of a line, NAME and then a line feed char
.*\n.* - two subsequent lines (.* matches zero or more chars other than line break chars as many as possible).
See the Swift fiddle:
import Foundation
let line_text = "NAME\nJESUS\nLASTNAME"
if let rng = line_text.range(of: #"(?m)(?<=^NAME\n).*\n.*"#, options: .regularExpression) {
print(String(line_text[rng]))
}
// => JESUS
// LASTNAME

Regex replace spaces at each new lines

I am saving users input to db as a string and I would like to remove all spaces at each lines.
Input from user:
Hi!
My name is:
Bob
I am from the USA.
I want to remove spaces between "Bob", so the result will be:
Hi!
My name is:
Bob
I am from the USA.
I am trying to do it with the following code
let regex = try! NSRegularExpression(pattern: "\n[\\s]+", options: .caseInsensitive)
a = regex.stringByReplacingMatches(in: a, options: [], range: NSRange(0..<a.utf16.count), withTemplate: "\n")
but this code replace multiple new lines "\n", I don't want to do it.
After I run the above code: "1\n\n\n 2" -> "1\n2". The result I need: "1\n\n\n2" (only spaces are removed, not new lines).
No need for regex, split the string on the new line character into an array and then trim all lines and join them together again
let trimmed = string.components(separatedBy: .newlines)
.map { $0.trimmingCharacters(in: .whitespaces) }
.joined(separator: "\n")
or you can use reduce
let trimmed = string.components(separatedBy: .newlines)
.reduce(into: "") { $0 += "\($1.trimmingCharacters(in: .whitespaces))\n"}
You can use
let regex = try! NSRegularExpression(pattern: "(?m)^\\h+", options: .caseInsensitive)
Actually, as there are no case chars in the pattern, you may remove .caseInsensitive and use:
let regex = try! NSRegularExpression(pattern: "(?m)^\\h+", options: [])
See the regex demo. The pattern means:
(?m) - turn on multiline mode
^ - due to (?m), it matches any line start position
\h+ - one or more horizontal whitespaces.
Swift code example:
let txt = "Hi!\n\nMy name is:\n Bob\n\nI am from the USA."
let regex = "(?m)^\\h+"
print( txt.replacingOccurrences(of: regex, with: "", options: [.regularExpression]) )
Output:
Hi!
My name is:
Bob
I am from the USA.

Remove whitespaces from a string

I referred this SO post to remove whitespaces and newline characters from a string. But in my string, I may have extra whitespaces as well as extra newline characters. I want to remove the unnecessary \n's and whitespaces from that string.
But if there is a string like so..."This \n is a st\tri\rng" then I don't want Thisisastring as the result but instead something like this..
This is a string
To replace contiguous spaces with a single space, replace Regular Expression \s+ with a single space:
let str = "This \n\n is a string"
if let regex = try? NSRegularExpression(pattern: "\\s+", options: NSRegularExpression.Options.caseInsensitive)
{
let result = regex.stringByReplacingMatches(in: str, options: [], range: NSMakeRange(0, str.count), withTemplate: " ")
print(result) //output: "This is a string"
}

trimmingCharacters not working as expected when characters include hyphen Swift

Trying to understand what is going wrong in playgrounds with the next example :
let result = "+-----+".trimmingCharacters(in: CharacterSet(charactersIn: "+").inverted)
result is "+-----+"
expected result is "++"
due to method reference "Returns a new string made by removing from both ends of the String characters contained in a given character set."
Examples that work how I expect:
let result = "D123ABC".trimmingCharacters(in: CharacterSet(charactersIn: "01234567890.").inverted)
result is "123"
let result = "+-----+".trimmingCharacters(in: CharacterSet(charactersIn: "*").inverted)
result is ""
trimmingCharacters only replaces the trailing/leading characters.
If you want to replace all characters that are not "+" you can use
"+-----+".replacingOccurrences(of: "[^+]", with: "", options: .regularExpression)
Agree with rmaddy.
For more explanation check this:
let result = "123+--+abc".trimmingCharacters(in: CharacterSet(charactersIn: "+").inverted)
Result: +--+
let result = "+--+".trimmingCharacters(in: CharacterSet(charactersIn: "+").inverted)
Result: +--+