Estrazione di sottostringhe in Go


114

Sto cercando di leggere un'intera riga dalla console (compresi gli spazi bianchi), quindi elaborarla. Usando bufio.ReadString, il carattere di nuova riga viene letto insieme all'input, quindi ho trovato il seguente codice per tagliare il carattere di nuova riga:

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

C'è un modo più idiomatico per farlo? Cioè, esiste già una libreria che si prende cura del byte nullo finale durante l'estrazione delle sottostringhe?

(Sì, so che esiste già un modo per leggere una riga senza il carattere di nuova riga in go readline -> string ma cerco di più un'elegante manipolazione delle stringhe.)

Risposte:


146

Sembra che tu sia confuso dal funzionamento delle sezioni e dal formato di archiviazione delle stringhe, che è diverso da quello che hai in C.

  • qualsiasi slice in Go memorizza la lunghezza (in byte), quindi non devi preoccuparti del costo lendell'operazione: non c'è bisogno di contare
  • Le stringhe Go non hanno terminazione null, quindi non è necessario rimuovere un byte null e non è necessario aggiungerlo 1dopo lo slicing aggiungendo una stringa vuota.

Per rimuovere l'ultimo carattere (se è un carattere di un byte), fallo semplicemente

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

11
Non hai nemmeno bisogno dello 0 (o :), s = s[:len(s)-1]andrà bene.
uriel

8
Tieni presente che questo metodo non funzionerà con le stringhe Unicode! groups.google.com/forum/#!msg/golang-nuts/ZeYei0IWrLg/…
Melllvar

@ Melllvar Ecco perché ho precisato "se è un carattere di un byte" . Se vuoi rimuovere un carattere che occupa più di un byte (non è il caso di OP), devi adattarti.
Denys Séguret

25

Le stringhe di Go non sono terminate da null e per rimuovere l'ultimo carattere di una stringa puoi semplicemente fare:

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

10
Questo non è corretto e causerà bug. Questo rimuove l'ultimo byte dalla stringa, il che potrebbe renderlo non valido UTF-8 (o altra codifica multibyte).
dott. Sybren

3
Vedi play.golang.org/p/K3HBBtj4Oi per un esempio di come si interrompe.
dott. Sybren

10

Per evitare il panico su un input di lunghezza zero, racchiudere l'operazione truncate in un if

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

9

Questo è quello più semplice per eseguire la sottostringa in 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

ATTENZIONE: operare solo su stringhe funzionerà solo con ASCII e conterà in modo errato quando l'input è un carattere non ASCII con codifica UTF-8 e probabilmente corromperà anche i caratteri poiché taglia i caratteri multibyte a metà sequenza.

Ecco una versione compatibile con 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
Ciò richiede molti più voti positivi: sono stato morso gravemente non usando la suddivisione consapevole di utf-8.
kolaente


2

8 anni dopo mi sono imbattuto in questa gemma, eppure non credo che la domanda originale di OP abbia davvero avuto risposta:

quindi ho creato il seguente codice per tagliare il carattere di nuova riga

Mentre il bufio.Readertipo supporta un ReadLine() metodo che rimuove sia \r\ned \nè inteso come una funzione di basso livello che è scomodo da usare perché sono necessari controlli ripetuti.

IMO un modo idiomatico per rimuovere gli spazi bianchi è usare la libreria di stringhe di 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)

Guarda questo esempio in azione nel parco giochi Golang: https://play.golang.org/p/HrOWH0kl3Ww

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.