Swift 3 replacingOccurrences of multiple strings - swift

I have JavaScript code that looks like the following:
foo.replace(/(\r\n|\n|\r)/gm, "");
Basically this strips any return carriages and new lines from my string. I'd like to do something similar in Swift 3.
I see func replacingOccurrences(of target: String, with replacement: String, options: CompareOptions = default, range searchRange: Range<Index>? = default) -> String is available. The problem is, this only takes one string in the of parameter.
Does this mean I need to call the method multiple times for each of my instances above, once for \r\n, once for \n\ and once for \r? Is there anyway to potentially accomplish something closer to what the regex is doing instead of calling replacingOccurrences three times?

Use replacingOccurrences with the option set to regularExpression.
let updated = foo.replacingOccurrences(of: "\r\n|\n|\r", with: "", options: .regularExpression)

To replace non-digits you can use "\D" as a regular expression
let numbers = "+1(202)-505-71-17".replacingOccurrences(of: "\\D", with: "", options: .regularExpression)
You can find how to use other regular expressions here

This one is pretty easy, it's all in the documentation.
let noNewlines = "a\nb\r\nc\r".replacingOccurrences(of: "\r\n|\n|\r", with: "", options: .regularExpression)

Related

Getting a empty Range<String.Index> in Swift

I am very new to Swift and have trying to use regular expressions, but getting the match from the string seems to be an insurmountable task.
This is my current approach.
print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression))))
This doesn't work because
Value of optional type 'Range<String.Index>?' must be unwrapped to a value of type 'Range<String.Index>'
I guess this has something to do with it possibly being null, so now i want to provide it with an alternative using the ?? operator.
print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression) ?? Range<String.Index>())))
What i want to do is to provide it with an empty range object but it seems to be impossible to create an empty object of the type required.
Any suggestions?
There is simply no argument-less initialiser for Range<String.Index>.
One way you can create an empty range of String.Index is to use:
data.startIndex..<data.startIndex
Remember that you shouldn't use integers here, because we are dealing with indices of a string. See this if you don't understand why.
So:
print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression) ?? data.startIndex..<data.startIndex)))
But substring(with:) is deprecated. You are recommended to use the subscript:
print(data[data.range(of: "[a-zA-Z]at", options: .regularExpression) ?? data.startIndex..<data.startIndex])
Instead of trying to create an empty range, I would suggest creating an empty Substring in case there was no match. Range can be quite error-prone, so using this approach you can save yourself a lot of headaches.
let match: Substring
if let range = data.range(of: "[a-zA-Z]at", options: .regularExpression) {
match = data[range]
} else {
match = ""
}
print(match)
You can create such constructor with a simple extension to Range type. Like this:
extension Range where Bound == String.Index {
static var empty: Range<Bound> {
"".startIndex..<"".startIndex
}
init() {
self = Range<Bound>.empty
}
}
Then it can be used like this:
let str = "kukukukuku"
let substr1 = str[str.range(of: "abc", options: .regularExpression) ?? Range<String.Index>()]
let substr2 = str[str.range(of: "abc", options: .regularExpression) ?? Range<String.Index>.empty]

Swift replace occurrence of string with condition

I have string like below
<p><strong>I am a strongPerson</strong></p>
I want to covert this string like this
<p><strong>I am a weakPerson</strong></p>
When I try below code
let old = "<p><strong>I am a strongPerson</strong></p>"
let new = old.replacingOccurrences(of: "strong", with: "weak")
print("\(new)")
I am getting output like
<p><weak>I am a weakPerson</weak></p>
But I need output like this
<p><strong>I am a weakPerson</strong></p>
My Condition here is
1.It has to replace only if word does not contain these HTML Tags like "<>".
Help me to get it. Thanks in advance.
You can use a regular expression to avoid the word being in a tag:
let old = "strong <p><strong>I am a strong person</strong></p> strong"
let new = old.replacingOccurrences(of: "strong(?!>)", with: "weak", options: .regularExpression, range: nil)
print(new)
I added some extra uses of the word "strong" to test edge cases.
The trick is the use of (?!>) which basically means to ignore any match that has a > at the end of it. Look at the documentation for NSRegularExpression and find the documentation for the "negative look-ahead assertion".
Output:
weak <p><strong>I am a weak person</strong></p> weak
Try the following:
let myString = "<p><strong>I am a strongPerson</strong></p>"
if let regex = try? NSRegularExpression(pattern: "strong(?!>)") {
let modString = regex.stringByReplacingMatches(in: myString, options: [], range: NSRange(location: 0, length: myString.count), withTemplate: "weak")
print(modString)
}

Swift: Checking Prefix with Regex

I am attempting to check if a string begins with a text that follows a regex pattern. Is there a way to do so using string.hasPrefix()?
My implementation so far:
let pattern = "[Ff][Yy][Ii](.)?"
let regex = try? NSRegularExpression(pattern: pattern, options: [])
if firstRowText.hasPrefix(regex) { //Cannot convert value of type NSRegularExpression to String
}
You should use a regex using range(of:options:range:locale:) passing the .regularExpression option with .anchored option:
if firstRowText.range(of: "[Ff][Yy][Ii]", options: [.regularExpression, .anchored]) != nil {...}
The .anchored option makes the regex engine search for a match at the start of the string only.
To make your regex match in a case insensitive way, you may pass another option alongside the current ones, .caseInsensitive, and use a shorter regex, like "FYI":
if firstRowText.range(of: "FYI", options: [.regularExpression, .anchored, .caseInsensitive]) != nil {
See the Swift online demo.
Note that you may also use an inline modifier option (?i) to set case insensitivity:
"(?i)FYI"

Swift finding and changing range in attributed string

What would be the best way to change this string:
"gain quickness for 5 seconds. <c=#reminder>(Cooldown: 90s)</c> only after"
into an Attributed String while getting rid of the part in the <> and I want to change the font of (Cooldown: 90s). I know how to change and make NSMutableAttributedStrings but I am stuck on how to locate and change just the (Cooldown: 90s) in this case. The text in between the <c=#reminder> & </c> will change so I need to use those to find what I need.
These seem to be indicators meant to be used for this purpose I just don't know ho.
First things first, you'll need a regular expression to find and replace all tagged strings.
Looking at the string, one possible regex could be <c=#([a-zA-Z-9]+)>([^<]*)</c>. Note that will will work only if the string between the tags doesn't contain the < character.
Now that we have the regex, we only need to apply it on the input string:
let str = "gain quickness for 5 seconds. <c=#reminder>(Cooldown: 90s)</c> only after"
let attrStr = NSMutableAttributedString(string: str)
let regex = try! NSRegularExpression(pattern: "<c=#([a-zA-Z-9]+)>([^<]*)</c>", options: [])
while let match = regex.matches(in: attrStr.string, options: [], range: NSRange(location: 0, length: attrStr.string.utf16.count)).first {
let indicator = str[Range(match.range(at: 1), in: str)!]
let substr = str[Range(match.range(at: 2), in: str)!]
let replacement = NSMutableAttributedString(string: String(substr))
// now based on the indicator variable you might want to apply some transformations in the `substr` attributed string
attrStr.replaceCharacters(in: match.range, with: replacement)
}

I need to remove this using encoding or decoding or replacement to remove \\U00b4 from string

I am getting I\\U00b4m in place of I'm. How to decode or replace this \\U00b4 from string ?
I\\U00b4m looking for the only one man in my life.
Easy way:
let aString = "This is my string"
let newString = aString.replacingOccurrences(of: "\U00b4", with: "", options: .literal, range: nil)
More info in here: Any way to replace characters on Swift String?