Mengekstrak substring di Go


114

Saya mencoba membaca seluruh baris dari konsol (termasuk spasi), lalu memprosesnya. Menggunakan bufio.ReadString, karakter baris baru dibaca bersama dengan input, jadi saya datang dengan kode berikut untuk memangkas karakter baris baru:

input,_:=src.ReadString('\n')
inputFmt:=input[0:len(input)-2]+"" //Need to manually add end of string

Apakah ada cara yang lebih idiomatis untuk melakukan ini? Artinya, apakah sudah ada pustaka yang menangani byte nol akhir saat mengekstrak substring untuk Anda?

(Ya, saya tahu sudah ada cara untuk membaca baris tanpa karakter baris baru di go readline -> string tetapi saya lebih mencari manipulasi string yang elegan.)

Jawaban:


146

Sepertinya Anda bingung dengan cara kerja irisan dan format penyimpanan string, yang berbeda dari yang Anda miliki di C.

  • setiap irisan di Go menyimpan panjangnya (dalam byte), jadi Anda tidak perlu peduli dengan biaya lenoperasinya: tidak perlu menghitung
  • String Go tidak diakhiri null, jadi Anda tidak perlu menghapus byte nol, dan Anda tidak perlu menambahkan 1setelah mengiris dengan menambahkan string kosong.

Untuk menghapus karakter terakhir (jika karakter satu byte), cukup lakukan

inputFmt:=input[:len(input)-1]

11
Anda bahkan tidak perlu 0 (atau :), s = s[:len(s)-1]sudah cukup.
uriel

8
Harap dicatat bahwa metode ini tidak akan berfungsi dengan string Unicode! groups.google.com/forum/#!msg/golang-nuts/ZeYei0IWrLg/…
Melllvar

@Melllvar Itu sebabnya saya menetapkan "jika itu adalah char satu byte" . Jika Anda ingin menghapus karakter yang mengambil lebih dari satu byte (itu bukan kasus OP), Anda harus beradaptasi.
Denys Séguret

25

String Go tidak diakhiri null, dan untuk menghapus karakter terakhir dari sebuah string, Anda cukup melakukan:

s = s[:len(s)-1]

10
Ini tidak benar dan akan menyebabkan bug. Ini menghilangkan byte terakhir dari string, yang dapat membuat UTF-8 tidak valid (atau encoding multibyte lainnya).
dr. Sybren

3
Lihat play.golang.org/p/K3HBBtj4Oi untuk contoh bagaimana ini rusak.
dr. Sybren

10

Untuk menghindari kepanikan pada input panjang nol, gabungkan operasi pemotongan dalam if

input, _ := src.ReadString('\n')
var inputFmt string
if len(input) > 0 {
    inputFmt = input[:len(input)-1]
}
// Do something with inputFmt

9

Ini adalah cara sederhana untuk melakukan substring di Go

package main

import "fmt"

var p = fmt.Println

func main() {

  value := "address;bar"

  // Take substring from index 2 to length of string
  substring := value[2:len(value)]
  p(substring)

}

7

PERINGATAN: beroperasi pada string saja hanya akan bekerja dengan ASCII dan akan dihitung salah jika input adalah karakter non-ASCII UTF-8 yang dikodekan, dan bahkan mungkin akan merusak karakter karena memotong karakter multibyte di tengah urutan.

Berikut adalah versi yang mendukung UTF-8:

func substr(input string, start int, length int) string {
    asRunes := []rune(input)

    if start >= len(asRunes) {
        return ""
    }

    if start+length > len(asRunes) {
        length = len(asRunes) - start
    }

    return string(asRunes[start : start+length])
}

1
Ini membutuhkan lebih banyak suara positif - Saya baru saja digigit dengan buruk karena tidak menggunakan pemisahan sadar utf-8.
kolaente


2

8 tahun kemudian saya menemukan permata ini, namun saya tidak percaya pertanyaan asli OP benar-benar terjawab:

jadi saya datang dengan kode berikut untuk memangkas karakter baris baru

Sementara bufio.Readertipe mendukung ReadLine() metode yang keduanya menghapus \r\ndan \nitu dimaksudkan sebagai fungsi tingkat rendah yang canggung untuk digunakan karena pemeriksaan berulang diperlukan.

IMO cara idiomatik untuk menghapus spasi adalah dengan menggunakan pustaka string Golang :

input, _ = src.ReadString('\n')

// more specific to the problem of trailing newlines
actual = strings.TrimRight(input, "\r\n")

// or if you don't mind to trim leading and trailing whitespaces 
actual := strings.TrimSpace(input)

Lihat contoh ini beraksi di taman bermain Golang: https://play.golang.org/p/HrOWH0kl3Ww

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.