Вилучення підрядів у Go


114

Я намагаюся прочитати цілий рядок з консолі (включаючи пробіли), а потім обробити його. Використовуючи bufio.ReadString, символ нового рядка читається разом із введенням, тому я придумав наступний код, щоб обрізати символ нового рядка:

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

Чи є ідіоматичніший спосіб зробити це? Тобто, чи існує вже бібліотека, яка піклується про закінчення нульового байта при вилученні підрядів для вас?

(Так, я знаю, що вже існує спосіб прочитати рядок без символу нової лінії в рядку go readline -> string, але я більше шукаю елегантну маніпуляцію з рядком.)

Відповіді:


146

Схоже, вас бентежить робота фрагментів та формат зберігання рядків, який відрізняється від того, що у вас є в C.

  • будь-який зріз у Go зберігає довжину (у байтах), тому вам не доведеться піклуватися про вартість lenоперації: не потрібно рахувати
  • Рядки "Go" не закінчуються, тому вам не доведеться видаляти нульовий байт, і вам не доведеться додавати 1після нарізки додаванням порожнього рядка.

Щоб видалити останній знак (якщо це однобайтовий графік), просто зробіть це

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

11
Вам навіть не потрібно 0 (або :), s = s[:len(s)-1]це зробить.
уріель

8
Зверніть увагу, що цей метод не працюватиме з рядками Unicode! groups.google.com/forum/#!msg/golang-nuts/ZeYei0IWrLg/…
Melllvar

@Melllvar Ось чому я чітко "якщо це однобайтовий знак" . Якщо ви хочете видалити знак, що містить більше одного байта (це не справа OP), вам доведеться адаптуватися.
Denys Séguret

25

Рядки Go не скасовуються на нуль, а для видалення останнього символу рядка ви можете просто зробити:

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

10
Це неправильно і призведе до помилок. Це знімає останній байт з рядка, що може зробити його недійсним UTF-8 (або іншим багатобайтовим кодуванням).
д-р. Sybren

3
Див. Play.golang.org/p/K3HBBtj4Oi для прикладу того, як це відбувається.
д-р. Sybren

10

Щоб уникнути паніки на вході нульової довжини, заверніть операцію обрізання у if

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

9

Це найпростіший для виконання підрядків у 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

ПОПЕРЕДЖЕННЯ. Операція лише з рядками буде працювати лише з ASCII і буде зараховуватися неправильно, коли вхід є символом, кодованим не ASCII UTF-8, і, ймовірно, навіть пошкодить символи, оскільки він скорочує багатобайтові символи в середині послідовності.

Ось версія 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
Це потребує більшої кількості оновлень - я просто сильно покусав, не використовуючи відомий розщеплення utf-8.
колаенте


2

Через 8 років я натрапив на цей дорогоцінний камінь, і все ж не вірю, що на оригінальне запитання ОП насправді відповіли:

тому я придумав наступний код, щоб обрізати символ нового рядка

Хоча bufio.Readerтип підтримує ReadLine() метод, який видаляє, \r\nі \nвін розуміється як функція низького рівня, яку незручно використовувати, оскільки необхідні повторні перевірки.

ІМО, ідіоматичний спосіб видалити пробіл - це використовувати бібліотеку рядків 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)

Дивіться цей приклад в дії на ігровому майданчику Golang: https://play.golang.org/p/HrOWH0kl3Ww

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.