在Swift中取消反斜杠

时间:2016-09-14 10:45:31

标签: swift string

我想在用户输入字符串中使用反斜杠来使用它们进行正则表达式替换。

使用NSRegularExpression.escapedTemplate(for: "\\n")轻松完成转义反斜杠。这会按预期返回"\\\\n"。但是,如何向后转换它们,例如\\n(反斜杠+ n)到\n(返回)?

4 个答案:

答案 0 :(得分:8)

我不认为可以自动执行此操作,但是,因为Swift中只有少量转义字符,您可以将它们放入数组中,循环遍历它们,然后将所有实例替换为未转义的版本。这是我做的字符串扩展:

extension String {
    var unescaped: String {
        let entities = ["\0", "\t", "\n", "\r", "\"", "\'", "\\"]
        var current = self
        for entity in entities {
            let descriptionCharacters = entity.debugDescription.characters.dropFirst().dropLast()
            let description = String(descriptionCharacters)
            current = current.replacingOccurrences(of: description, with: entity)
        }
        return current
    }
}

要使用它,只需访问该属性即可。例如,

print("Hello,\\nWorld!".unescaped) 

将打印

Hello,
World!

答案 1 :(得分:2)

我已经改进了@ kabiroberai的代码,使其更具功能性并删除剩余的单个反斜杠。

extension String {
    var unescaped: String {
        let entities = ["\0": "\\0",
                        "\t": "\\t",
                        "\n": "\\n",
                        "\r": "\\r",
                        "\"": "\\\"",
                        "\'": "\\'",
                        ]

        return entities
            .reduce(self) { (string, entity) in
                string.replacingOccurrences(of: entity.value, with: entity.key)
            }
            .replacingOccurrences(of: "\\\\(?!\\\\)", with: "", options: .regularExpression)
            .replacingOccurrences(of: "\\\\", with: "\\")
    }
}

更新

我发现我之前的代码在某些情况下无法正常使用。

所以,我更新了我的生产代码。以下是我使用的最新版本。 我不确定我是否真的需要做这个复杂的过程,但现在似乎工作得更好。

var unescaped: String {
    let entities = ["\0": "0",
                    "\t": "t",
                    "\n": "n",
                    "\r": "r",
                    "\"": "\"",
                    "\'": "'",
                    ]

    return entities
        .mapValues { try! NSRegularExpression(pattern: "(?<!\\\\)(?:\\\\\\\\)*(\\\\" + $0 + ")") }
        .reduce(self) { (string, entity) in
            entity.value.matches(in: string, range: string.nsRange)
                .map { $0.range(at: 1) }
                .reversed()
                .reduce(string) { ($0 as NSString).replacingCharacters(in: $1, with: entity.key) }
        }
}

答案 2 :(得分:1)

我认为这是使用stringByReplacingOccurrencesOfString

的最简单方法
let input = "My name is \\n and \\n"
let firstmod = input.stringByReplacingOccurrencesOfString("\\n", withString: "\n", options: [], range: nil)

Input : "My name is \\n and \\n"
Output: "My name is \n and \n"

答案 3 :(得分:0)

这是我对字符串的转义和未转义

let given =     "{\n\t\"test\": \"this ? \\ \",\n\r\t\"\'testing\': 1\r\n}\\ \0 \\"
let expected = #"{\n\t\"test\": \"this ? \\ \",\n\r\t\"\'testing\': 1\r\n}\\ \0 \\"#
let expectedAscii = #"{\n\t\"test\": \"this \u{0001F603} \\ \",\n\r\t\"\'testing\': 1\r\n}\\ \0 \\"#

extension String {
    private static let escapedChars = [
        (#"\0"#, "\0"),
        (#"\t"#, "\t"),
        (#"\n"#, "\n"),
        (#"\r"#, "\r"),
        (#"\""#, "\""),
        (#"\'"#, "\'"),
        (#"\\"#, "\\")
    ]
    var escaped: String {
        self.unicodeScalars.map { $0.escaped(asASCII: false) }.joined()
    }
    var asciiEscaped: String {
        self.unicodeScalars.map { $0.escaped(asASCII: true) }.joined()
    }
    var unescaped: String {
        var result: String = self
        String.escapedChars.forEach {
            result = result.replacingOccurrences(of: $0.0, with: $0.1)
        }
        return result
    }
}

print(expected == given.escaped)
print(expectedAscii == given.asciiEscaped)
print(given.escaped.unescaped == given)
print(expected.unescaped == given)
print(expected.unescaped.escaped == expected)