亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Golang 替換所有換行符

Golang 替換所有換行符

Go
阿波羅的戰車 2023-04-17 15:17:39
通常,當我替換換行符時,我會跳轉到正則表達式,就像在這個 PHP 中一樣preg_replace('/\R/u', "\n", $String);因為我知道這是替換任何類型的 Unicode 換行符(無論是 \n、\r、\r\n 等)的一種非常持久的方法我也在嘗試在 Go 中做這樣的事情,但我得到了解析正則表達式時出錯:轉義序列無效:\R在這條線上msg = regexp.MustCompilePOSIX("\\R").ReplaceAllString(html.EscapeString(msg), "<br>\n")我嘗試使用(?:(?>\r\n)|\v)https://stackoverflow.com/a/4389171/728236 ,但看起來 Go 的正則表達式實現也不支持它,恐慌invalid or unsupported Perl syntax: '(?>'什么是替換 Go 中的換行符的好、安全的方法,Regex 與否?我在這里看到這個答案Golang:Issues replacing newlines in a string from a text file saying to use \r?\n,但我猶豫是否相信它會得到所有Unicode 換行符,主要是因為這個問題的答案列出了比覆蓋的3個\r?\n,
查看完整描述

2 回答

?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

雖然使用 regexp 通常會產生一個優雅而緊湊的解決方案,但它通常不是最快的。

對于必須用其他子字符串替換某些子字符串的任務,標準庫以以下形式提供了一個非常有效的解決方案strings.Replacer

Replacer 用替換項替換字符串列表。多個 goroutines 并發使用是安全的。

您可以使用創建可重復使用的替換器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 答案中的正則表達式解決方案:


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")

}

實施實際上相當快。這是一個簡單的基準測試,將其與上述預編譯的正則表達式解決方案進行比較:


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 倍strings.Replacer以上。

還有另一個優點。在上面的示例中,我們將結果作為新string值獲取(在兩種解決方案中)。這需要一個新的string分配。如果我們需要將結果寫入一個io.Writer(例如,我們正在創建一個 HTTP 響應或將結果寫入一個文件),我們可以避免必須創建新的,string因為strings.Replacer它有一個方便的Replacer.WriteString()方法,它接受一個io.Writer并寫入result into 它而不分配并將其作為 a 返回string。與正則表達式解決方案相比,這進一步顯著提高了性能增益。


查看完整回答
反對 回復 2023-04-17
?
心有法竹

TA貢獻1866條經驗 獲得超5個贊

您可以將模式“解碼”\R為


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

請參閱解釋速記的Java 正則表達式文檔\R:


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 演示。


一些 Unicode 代碼可以用Go regexp支持的正則表達式轉義序列替換:


re := regexp.MustCompile(`\r\n|[\r\n\v\f\x{0085}\x{2028}\x{2029}]`)


查看完整回答
反對 回復 2023-04-17
  • 2 回答
  • 0 關注
  • 397 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號