Extraindo substrings em Go


114

Estou tentando ler uma linha inteira do console (incluindo os espaços em branco) e processá-la. Usando bufio.ReadString, o caractere de nova linha é lido junto com a entrada, então eu vim com o seguinte código para cortar o caractere de nova linha:

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

Existe uma maneira mais idiomática de fazer isso? Ou seja, já existe uma biblioteca que cuida do byte nulo final ao extrair substrings para você?

(Sim, eu sei que já existe uma maneira de ler uma linha sem o caractere de nova linha em go readline -> string, mas estou procurando mais por manipulação de string elegante.)

Respostas:


146

Parece que você está confuso com o funcionamento das fatias e o formato de armazenamento da string, que é diferente do que você tem em C.

  • qualquer fatia em Go armazena o comprimento (em bytes), então você não precisa se preocupar com o custo da lenoperação: não há necessidade de contar
  • As strings de Go não têm terminação nula, então você não precisa remover um byte nulo e não precisa adicionar 1depois de fatiar adicionando uma string vazia.

Para remover o último caractere (se for um caractere de um byte), basta fazer

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

11
Você nem precisa do 0 (ou do :), s = s[:len(s)-1]basta.
uriel

8
Observe que este método não funcionará com strings Unicode! groups.google.com/forum/#!msg/golang-nuts/ZeYei0IWrLg/…
Melllvar

@Melllvar É por isso que eu precisei "se for um caractere de um byte" . Se você quiser remover um char que ocupa mais de um byte (não é o caso do OP), você tem que se adaptar.
Denys Séguret

25

Strings Go não têm terminação nula e, para remover o último caractere de uma string, você pode simplesmente fazer:

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

10
Isso está incorreto e causará bugs. Isso remove o último byte da string, o que pode torná-la UTF-8 inválida (ou outra codificação multibyte).
dr. Sybren

3
Consulte play.golang.org/p/K3HBBtj4Oi para um exemplo de como isso quebra.
dr. Sybren

10

Para evitar o pânico em uma entrada de comprimento zero, envolva a operação de truncamento em um if

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

9

Este é o método simples de executar substring no 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

AVISO: operar apenas em strings funcionará apenas com ASCII e contará incorretamente quando a entrada for um caractere não codificado em ASCII UTF-8, e provavelmente até corromperá caracteres, pois corta caracteres multibyte no meio da sequência.

Esta é uma versão compatível com 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
Isso precisa de muito mais votos positivos - acabei de ser mordido gravemente por não usar a divisão ciente de utf-8.
kolaente


2

8 anos depois, descobri esta joia, mas não acredito que a pergunta original da OP tenha sido realmente respondida:

então eu vim com o seguinte código para cortar o caractere de nova linha

Enquanto o bufio.Readertipo suporta um ReadLine() método que remove \r\ne \né concebido como uma função de baixo nível, que é difícil de usar porque verificações repetidas são necessárias.

IMO, uma forma idiomática de remover espaços em branco é usar a biblioteca de strings 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)

Veja este exemplo em ação no playground Golang: https://play.golang.org/p/HrOWH0kl3Ww

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.