代码之家  ›  专栏  ›  技术社区  ›  Brian Leishman

Golang替换所有换行符

  •  2
  • Brian Leishman  · 技术社区  · 7 年前

    preg_replace('/\R/u', "\n", $String);
    

    因为我知道这是一种非常持久的方式来替换任何类型的Unicode换行符(无论是\n、\r、\r\n等等)

    分析regexp时出错:转义序列无效: \R

    在这条线上

    msg = regexp.MustCompilePOSIX("\\R").ReplaceAllString(html.EscapeString(msg), "<br>\n")
    

    (?:(?>\r\n)|\v) https://stackoverflow.com/a/4389171/728236 ,但看起来Go的regex实现也不支持这一点 invalid or unsupported Perl syntax: '(?>'

    什么是一个好的,安全的方式来取代新行在围棋,Regex与否?


    我在这里看到了这个答案 Golang: Issues replacing newlines in a string from a text file \r?\n 全部的 Unicode新行,主要是因为这个问题的答案列出了比3个

    2 回复  |  直到 7 年前
        1
  •  3
  •   Wiktor Stribiżew    7 年前

    你可以“解码”这个 \R 图案组件

    U+000DU+000A|[U+000AU+000BU+000CU+000DU+0085U+2028U+2029]
    

    看到了吗 Java regex docs 解释 \右 速记:

    Linebreak matcher
    \R  Any Unicode linebreak sequence, is equivalent to \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

    在Go中,您可以使用以下选项:

    func removeLBR(text string) string {
        re := regexp.MustCompile(`\x{000D}\x{000A}|[\x{000A}\x{000B}\x{000C}\x{000D}\x{0085}\x{2028}\x{2029}]`)
        return re.ReplaceAllString(text, ``)
    }
    

    Go demo .

    Go regexp :

    re := regexp.MustCompile(`\r\n|[\r\n\v\f\x{0085}\x{2028}\x{2029}]`)
    
        2
  •  5
  •   icza    7 年前

    虽然使用regexp通常会产生一个优雅而紧凑的解决方案,但它通常不是最快的。

    strings.Replacer :

    Replacer用replacements替换字符串列表。它对于多个goroutine并发使用是安全的。

    strings.NewReplacer() ,其中列出包含可替换零件及其替换件的对。当您要执行替换时,只需调用 Replacer.Replace()

    下面是它的样子:

    const replacement = "<br>\n"
    
    var replacer = strings.NewReplacer(
        "\r\n", replacement,
        "\r", replacement,
        "\n", replacement,
        "\v", replacement,
        "\f", replacement,
        "\u0085", replacement,
        "\u2028", replacement,
        "\u2029", replacement,
    )
    
    func replaceReplacer(s string) string {
        return replacer.Replace(s)
    }
    

    Wiktor's answer 看起来像:

    var re = regexp.MustCompile(`\r\n|[\r\n\v\f\x{0085}\x{2028}\x{2029}]`)
    
    func replaceRegexp(s string) string {
        return re.ReplaceAllString(s, "<br>\n")
    }
    

    其实实施速度相当快。下面是一个简单的基准测试,将其与上述预编译的regexp解决方案进行比较:

    const input = "1st\nsecond\r\nthird\r4th\u0085fifth\u2028sixth"
    
    func BenchmarkReplacer(b *testing.B) {
        for i := 0; i < b.N; i++ {
            replaceReplacer(input)
        }
    }
    
    func BenchmarkRegexp(b *testing.B) {
        for i := 0; i < b.N; i++ {
            replaceRegexp(input)
        }
    }
    

    以及基准结果:

    BenchmarkReplacer-4      3000000               495 ns/op
    BenchmarkRegexp-4         500000              2787 ns/op
    

    超过 5次

    还有另一个优势。在上面的例子中,我们得到了一个新的结果 string 价值(在两种解决方案中)。这需要一个新的 分配。如果我们需要将结果写入 io.Writer (例如,我们正在创建一个HTTP响应或将结果写入一个文件),我们可以避免创建新的 一串 万一 字符串。替换 因为它有一个方便的 Replacer.WriteString() 方法需要 并将结果写入其中,而不将其作为 一串 . 与regexp解决方案相比,这进一步显著提高了性能增益。