Combine multiple replacingOccurrences() with Swift - ios

I have a String, I would like to add backslash to specific characters, because I use markdown and I don't wand to add style it's not wanted.
I tried to make a function, and it's working, but it's not efficient I guess:
func escapeMarkdownCharacters(){
let myString = "This is #an exemple #of _my_ * function"
var modString = myString.replacingOccurrences(of: "#", with: "\\#")
modString = modString.replacingOccurrences(of: "*", with: "\\*")
modString = modString.replacingOccurrences(of: "_", with: "\\_")
print(modString) // Displayed: This is \#an exemple \#of \_my\_ \* function
}
I would like to only have one "replacingOccurences" that work for multiple characters. I think I could do that with regex but I didn't figure out how. If you have an idea, please share it with me.

You may use
var modString = myString.replacingOccurrences(of: "[#*_]", with: "\\\\$0", options: [.regularExpression])
With a raw string literal:
var modString = myString.replacingOccurrences(of: "[#*_]", with: #"\\$0"#, options: [.regularExpression])
Result: This is \#an exemple \#of \_my\_ \* function
The options: [.regularExpression] argument enables the regex search mode.
The [#*_] pattern matches #, * or _ and then each match is replaced with a backslash (\\\\) and the match value ($0). Note that the backslash must be doubled in the replacement string because a backslash has a special meaning inside a replacement pattern (it may be used to make $0 a literal string when $ is preceded with a backslash).

Related

Swift: how to suppress interpretation of special characters and provide string literal

The goal is to serialize a Swift object by converting it to a JSON object then converting the JSON object into a JSON string that can be passed over the wire and decoded on the other side.
The problem is producing a valid JSON string.
Newlines must be escaped in a JSON string, but Swift interprets special characters in the escaped string instead of treating the string as a literal.
For example:
let a = "foobar\nhello\nworld"
let escapedString = a.replacingOccurrences(of: "\n", with: "\\n")
print(escapedString)
What gets printed is foobar\nhello\nworld instead of the desired foobar\\nhello\\nworld.
How do you tell Swift to treat a string as a literal and not to interpret special characters within?
UPDATE
As OOPer points out, using debugPrint shows the \\n characters remaining intact.
However, when paired with evaluateJavaScript in WKWebView, the \\n characters are turned into \n, which is the root issue. For example:
let script = "\(callback)(\'\(escapedString)\')"
webView!.evaluateJavaScript(script) { (object: Any?, error: Error?) -> Void in
print("Done invoking \(callback)")
}
There is no unescaped string syntax like in javascript template literals which is probably what you are looking for; maybe they will add it in the future. Unfortunately you therefore have to escape each back slash which sometimes looks very scray, as in your example.
//This is the same as `foobar\nhello\nworld` where each char is a literal
let a = "foobar\\nhello\\nworld"
let escapedString = a.replacingOccurrences(of: "\\n", with: "\\\\n")
//This outputs `foobar\\nhello\\nworld`
print(escapedString)
Maybe you are just mistaking to interpret the output from print.
When you get foobar\nhello\nworld from print(escapedString), escapedString contains 20 characters -- f o o b a r \ n h e l l o \ n w o r l d.
This is a valid JSON string when enclosed between "s.
If you want to check the escaped result in String-literal-like notation, you can use debugPrint:
let a = "foobar\nhello\nworld"
let escapedString = a.replacingOccurrences(of: "\n", with: "\\n")
print(escapedString) //->foobar\nhello\nworld
debugPrint(escapedString) //->"foobar\\nhello\\nworld"
For UPDATE
When using with evaluateJavaScript, you'd better think what is the right code as JavaScript, if you want to represent a JSON escaped string in JavaScript, you would write in .js file (or in <script>...</script>):
someFunc('foobar\\nhello\\nworld');
So, you may need to write something like this:
let a = "foobar\nhello\nworld"
let escapedForJSON = a.replacingOccurrences(of: "\n", with: "\\n")
//In actual code, you may need a little more...
let escapedForJavaScriptString = escapedForJSON.replacingOccurrences(of: "\\", with: "\\\\")
let script = "\(callback)(\'\(escapedForJavaScriptString)\')"
webView!.evaluateJavaScript(script) { (object: Any?, error: Error?) -> Void in
print("Done invoking \(callback)")
}

swift ios alpha numeric regex that allows underscores and dashes

I am using this lib for validation and are trying to add my own regex.
What I want to do is to make a regex that allows alphanumeric A-Z 0-9 together with dashes and unserscores -_
I have tryed let regex = "[a-zA-Z0-9_-]" but I cant get it to work.
I also want the regex to not only allow english letters, but all languishes.
The lib works cause I have made another regex that only allows ints 0-9 which works
let intRegex = "^[0-9]*$"
Your regex look good but it will only match a single character. Do this "^[a-zA-Z0-9_-]*$" instead to match more than one character.
breakup --
^ -- start of string
[\pL0-9_-] -- characters you want to allow
* -- any number of characters (the crucial bit you were missing)
$ -- end of string
Building up on #charsi's answer
extension String {
var isAlphanumericDashUnderscore: Bool {
get {
let regex = try! NSRegularExpression(pattern: "^[a-zA-Z0-9_-]*$", options: .caseInsensitive)
return regex.firstMatch(in: self, options: [], range: NSRange(location: 0, length: count)) != nil
}
}
}

Swift regex to match unicodes

I am new to swift and want to match all the unicode strings using regex
For example:
var s="😀 emoji 😀"
When I decoded the above string the result is:
"\ud83d\ude00 emoji \ud83d\ude00"
I want to replace each emoji with say *
In java I used the regex as:
"[\uD800-\uDBFF\uDC00-\uDFFF]" and was working
In swift I am using the same regex but its replacing every character with *
I want the result as * emoji *
Help is highly appreciated
The Unicode code point of the emoji you have shown is U+1F600.
(Unicode 9.0 Character Code Charts - Emoticons)
And your regex pattern (which may work for UTF-16 representation) [\uD800-\uDBFF\uDC00-\uDFFF] matches all non-BMP characters -- U+10000...U+10FFFF, which contains most of all emojis but also contains huge non-emoji characters.
So, as you say "[\uD800-\uDBFF\uDC00-\uDFFF]" was working, the equivalent pattern in NSRegularExpression is "[\\U00010000-\\U0010FFFF]".
var s="😀 emoji 😀"
let regex = try! NSRegularExpression(pattern: "[\\U00010000-\\U0010FFFF]", options: [])
let replaced = regex.stringByReplacingMatchesInString(s, options: [], range: NSRange(0..<s.utf16.count), withTemplate: "*") //->"* emoji *"
(Addition)
To see Unicode code points in your string literal:
s.unicodeScalars.forEach {
print(String(format: "U+%04X ", Int($0.value)))
}
For your example string, I get:
U+1F600
U+0020
U+0065
U+006D
U+006F
U+006A
U+0069
U+0020
U+1F600

Swift - Regular Expression to match parentheses

I am trying to use regex to search through a string: "K1B92 (D) [56.094]" and I want to grab the "(D)" including the parentheses surrounding the "D". I am having trouble finding the correct expression to match the actual parentheses as simply putting parentheses will take it as a block and trying to escape the parentheses with "\" making it think its an expression to be evaluated. I also tried escaping "\(" with "\\(" as so: "\\([ABCD])\\)" but without luck. This is the code I have been using:
let str = "K1B92 (D) [56.094]"
let regex = NSRegularExpression(pattern: "\\b\\([ABCD])\\)\\b", options: NSRegularExpressionOptions.CaseInsensitive, error: nil)
let match = regex?.firstMatchInString(str, options: NSMatchingOptions.WithoutAnchoringBounds, range: NSMakeRange(0, count(str)))
let strRange = match?.range
let start = strRange?.location
let length = strRange?.length
let subStr = str.substringWithRange(Range<String.Index>(start: advance(str.startIndex, start!), end: advance(str.startIndex, start! + length!)))
// "\\b\([ABCD])\)\\b" returns range only for the letter "D" without parentheses.
// "\\b\\([ABCD])\\)\\b" returns nil
Can direct me towards the correct expression please? Thank you very much.
The \\([ABCD])\\) part is OK,
Correction: As #vacawama correctly said in his answer, the parentheses
do not match here. \\([ABCD]\\) matches one of the letters A-D
enclosed in parentheses.
The other problem is that there is no word boundary
(\b pattern) between a space and a parenthesis.
So you could either (depending on your needs), just remove the \b patterns, or replace them by \s for white space:
let regex = NSRegularExpression(pattern: "\\s\\([ABCD]\\)\\s", ...
But since the matched string should not include the space you need
a capture group:
let regex = NSRegularExpression(pattern: "\\s(\\([ABCD]\\))\\s", ...
// ...
let strRange = match?.rangeAtIndex(1)
The regular expression you need is "\\([ABCD]\\)". You need the double escape \\ before both open paren ( and close paren ).

How to use Lua gsub to remove '<!--more--> correctly?

I have a string that might contains '<!--more-->' and I am trying to remove it by using this code
local str = string.gsub (string, "<!--more-->", "")
but it doesn't work. The string still contains it.
I try with this
local str = string.gsub (string, "[<!--more-->]", "")
but it has an 'e' left.
The - character is special in patterns. You need to escape it:
local str = string.gsub (string, "<!%-%-more%-%->", "")

Resources