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

mark2222
fonte

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]
Denys Séguret
fonte
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]
Uriel
fonte
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
Rohanthewiz
fonte
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)

}
Faris Rayhan
fonte
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])
}
joonas.fi
fonte
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

Philipp Pixel
fonte