Teilzeichenfolgen in Go extrahieren

114

Ich versuche, eine ganze Zeile von der Konsole zu lesen (einschließlich Leerzeichen) und sie dann zu verarbeiten. Mit bufio.ReadString wird das Zeilenumbruchzeichen zusammen mit der Eingabe gelesen, sodass ich den folgenden Code zum Trimmen des Zeilenumbruchzeichens gefunden habe:

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

Gibt es einen idiomatischeren Weg, dies zu tun? Gibt es bereits eine Bibliothek, die sich beim Extrahieren von Teilzeichenfolgen um das End-Null-Byte kümmert?

(Ja, ich weiß, dass es bereits eine Möglichkeit gibt, eine Zeile ohne das Zeilenumbruchzeichen in go readline -> string zu lesen, aber ich suche eher nach einer eleganten String-Manipulation.)

mark2222
quelle

Antworten:

146

Es sieht so aus, als wären Sie verwirrt von der Arbeit mit Slices und dem String-Speicherformat, das sich von dem in C unterscheidet.

  • Jedes Slice in Go speichert die Länge (in Bytes), sodass Sie sich nicht um die Kosten der lenOperation kümmern müssen: Sie müssen nicht zählen
  • Go-Zeichenfolgen sind nicht nullterminiert, sodass Sie kein Nullbyte entfernen und 1nach dem Schneiden keine leere Zeichenfolge hinzufügen müssen.

Um das letzte Zeichen zu entfernen (wenn es sich um ein 1-Byte-Zeichen handelt), tun Sie dies einfach

inputFmt:=input[:len(input)-1]
Denys Séguret
quelle
11
Sie brauchen nicht einmal die 0 (oder die :), s = s[:len(s)-1]wird reichen.
Uriel
1
Vielen Dank für die Klarstellung; Es scheint, dass am Ende der von der ReadString-Funktion zurückgegebenen Zeichenfolge zwei Leerzeichen standen, daher habe ich eines für ein Null-Byte gehalten. Entschuldigen Sie die Verwechslung mit C-Strings. Ich habe fmt zusammen mit bufio verwendet, was dazu führte, dass lustige Dinge in der Konsole auftauchten, also dachte ich, es könnte das schmutzige Null-Byte sein. Nur eine abschließende Klarstellung - was könnte das zusätzliche Leerzeichen von ReadString sein?
Mark2222
Ok, ich werde meine eigene Frage beantworten - es ist \ r dann \ n: P Die lustige Konsolenausgabe war, weil ich \ r ohne \ n ausgegeben habe.
Mark2222
8
Bitte beachten Sie, dass diese Methode nicht mit Unicode-Strings funktioniert! groups.google.com/forum/#!msg/golang-nuts/ZeYei0IWrLg/…
Melllvar
@ Melllvar Deshalb habe ich "wenn es ein Ein-Byte- Zeichen ist " präzisiert . Wenn Sie ein Zeichen entfernen möchten, das mehr als ein Byte benötigt (dies ist nicht der Fall von OP), müssen Sie es anpassen.
Denys Séguret
25

Go-Zeichenfolgen sind nicht nullterminiert. Um das letzte Zeichen einer Zeichenfolge zu entfernen, können Sie einfach Folgendes tun:

s = s[:len(s)-1]
Uriel
quelle
10
Dies ist falsch und führt zu Fehlern. Dadurch wird das letzte Byte von der Zeichenfolge entfernt, wodurch UTF-8 (oder eine andere Multibyte-Codierung) möglicherweise ungültig wird.
dr. Sybren
3
Ein Beispiel dafür, wie dies funktioniert, finden Sie unter play.golang.org/p/K3HBBtj4Oi .
dr. Sybren
10

Um eine Panik bei einer Eingabe mit der Länge Null zu vermeiden, schließen Sie die Kürzungsoperation in ein if ein

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

Dies ist die einfache Möglichkeit, Teilzeichenfolgen in Go auszuführen

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
quelle
7

WARNUNG: Die alleinige Bearbeitung von Zeichenfolgen funktioniert nur mit ASCII und zählt falsch, wenn die Eingabe ein nicht ASCII-UTF-8-codiertes Zeichen ist. Wahrscheinlich werden sogar Zeichen beschädigt, da Multibyte-Zeichen in der Mitte der Sequenz geschnitten werden.

Hier ist eine UTF-8-fähige Version:

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
quelle
1
Dies erfordert viel mehr Upvotes - ich wurde nur schwer gebissen, weil ich keine utf-8-bewusste Aufteilung verwendet habe.
Kolaente
2

8 Jahre später bin ich auf dieses Juwel gestoßen, und dennoch glaube ich nicht, dass die ursprüngliche Frage von OP wirklich beantwortet wurde:

Deshalb habe ich mir den folgenden Code ausgedacht, um das Zeilenumbruchzeichen zu kürzen

Während die bufio.ReaderArt unterstützt eine ReadLine() Methode , die beide entfernt \r\nund \nes wird als eine Low-Level - Funktion zu verstehen , die zur Benutzung umständlich ist , weil wiederholte Kontrollen notwendig sind.

IMO ist eine idiomatische Möglichkeit, Leerzeichen zu entfernen, die Verwendung der Strings- Bibliothek von 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)

Sehen Sie dieses Beispiel in Aktion auf dem Golang-Spielplatz: https://play.golang.org/p/HrOWH0kl3Ww

Philipp Pixel
quelle