Extraction de sous-chaînes dans Go

114

J'essaie de lire une ligne entière à partir de la console (y compris les espaces), puis de la traiter. En utilisant bufio.ReadString, le caractère de nouvelle ligne est lu avec l'entrée, j'ai donc proposé le code suivant pour couper le caractère de nouvelle ligne:

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

Y a-t-il une manière plus idiomatique de faire cela? Autrement dit, existe-t-il déjà une bibliothèque qui prend en charge l'octet nul de fin lors de l'extraction de sous-chaînes pour vous?

(Oui, je sais qu'il existe déjà un moyen de lire une ligne sans le caractère de nouvelle ligne dans go readline -> string mais je recherche davantage une manipulation de chaîne élégante.)

mark2222
la source

Réponses:

146

Il semble que vous soyez confus par le fonctionnement des tranches et le format de stockage des chaînes, qui est différent de ce que vous avez en C.

  • toute tranche de Go stocke la longueur (en octets), vous n'avez donc pas à vous soucier du coût de l' lenopération: il n'est pas nécessaire de compter
  • Les chaînes Go ne sont pas terminées par null, vous n'avez donc pas à supprimer un octet nul, et vous n'avez pas à ajouter 1après le découpage en ajoutant une chaîne vide.

Pour supprimer le dernier caractère (s'il s'agit d'un caractère d'un octet), faites simplement

inputFmt:=input[:len(input)-1]
Denys Séguret
la source
11
Vous n'avez même pas besoin du 0 (ou du :), s = s[:len(s)-1]fera l'affaire.
uriel
8
Veuillez noter que cette méthode ne fonctionnera pas avec les chaînes Unicode! groups.google.com/forum/#!msg/golang-nuts/ZeYei0IWrLg/…
Melllvar
@Melllvar C'est pourquoi j'ai précisé "si c'est un caractère d'un octet" . Si vous voulez supprimer un caractère prenant plus d'un octet (ce n'est pas le cas d'OP), vous devez vous adapter.
Denys Séguret
25

Les chaînes Go ne sont pas terminées par null, et pour supprimer le dernier caractère d'une chaîne, vous pouvez simplement faire:

s = s[:len(s)-1]
Uriel
la source
10
Ceci est incorrect et provoquera des bogues. Cela supprime le dernier octet de la chaîne, ce qui peut la rendre invalide UTF-8 (ou autre encodage multi-octets).
dr. Sybren
3
Voir play.golang.org/p/K3HBBtj4Oi pour un exemple de la façon dont cela se brise.
dr. Sybren
10

Pour éviter une panique sur une entrée de longueur nulle, encapsulez l'opération de troncature dans un if

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

C'est le plus simple pour effectuer une sous-chaîne dans 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)

}
Faris Rayhan
la source
7

AVERTISSEMENT: n'opérer que sur des chaînes ne fonctionnera qu'avec ASCII et comptera mal lorsque l'entrée est un caractère non encodé en ASCII UTF-8, et corrompra probablement même les caractères car il coupe les caractères multi-octets au milieu de la séquence.

Voici une version compatible 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])
}
joonas.fi
la source
1
Cela nécessite beaucoup plus de votes positifs - je viens de me faire mordre en n'utilisant pas le fractionnement conscient de utf-8.
kolaente le
2

8 ans plus tard, je suis tombé sur ce joyau, et pourtant je ne pense pas que la question initiale d'OP ait vraiment été répondue:

donc j'ai trouvé le code suivant pour couper le caractère de nouvelle ligne

Alors que le bufio.Readertype prend en charge une ReadLine() méthode qui supprime à la fois \r\net \nqu'il est conçu comme une fonction de bas niveau qui est difficile à utiliser car des vérifications répétées sont nécessaires.

IMO, un moyen idiomatique de supprimer les espaces est d'utiliser la bibliothèque de chaînes de 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)

Voir cet exemple en action dans le terrain de jeu de Golang: https://play.golang.org/p/HrOWH0kl3Ww

Philipp Pixel
la source