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

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]

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]

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

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)

}

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])
}

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.