Trích xuất chuỗi con trong Go


114

Tôi đang cố đọc toàn bộ dòng từ bảng điều khiển (bao gồm cả khoảng trắng), sau đó xử lý nó. Sử dụng bufio.ReadString, ký tự dòng mới được đọc cùng với đầu vào, vì vậy tôi đã nghĩ ra đoạn mã sau để cắt ký tự dòng mới:

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

Có cách nào dễ hiểu hơn để làm điều này không? Tức là đã có thư viện xử lý byte null kết thúc khi giải nén chuỗi con cho bạn chưa?

(Có, tôi biết đã có một cách để đọc một dòng mà không có ký tự dòng mới trong go readline -> string nhưng tôi đang tìm kiếm nhiều hơn về thao tác chuỗi thanh lịch.)

Câu trả lời:


146

Có vẻ như bạn đang bối rối trước hoạt động của các lát cắt và định dạng lưu trữ chuỗi, khác với những gì bạn có trong C.

  • bất kỳ lát cắt nào trong Go đều lưu trữ độ dài (tính bằng byte), vì vậy bạn không phải quan tâm đến chi phí của lenhoạt động: không cần phải đếm
  • Các chuỗi đi không được kết thúc bằng null, vì vậy bạn không phải xóa một byte rỗng và bạn không phải thêm 1sau khi cắt bằng cách thêm một chuỗi rỗng.

Để loại bỏ ký tự cuối cùng (nếu đó là ký tự một byte), chỉ cần thực hiện

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

11
Bạn thậm chí không cần số 0 (hoặc :), s = s[:len(s)-1]sẽ làm được.
tiểu

1
Cảm ơn rất nhiều vì đã làm rõ; Có vẻ như có hai ký tự khoảng trắng ở cuối chuỗi được trả về từ hàm ReadString, vì vậy tôi đã nhầm một ký tự với byte rỗng. Xin lỗi vì sự nhầm lẫn với chuỗi C; Tôi đang sử dụng fmt cùng với bufio dẫn đến nội dung buồn cười xuất hiện trong bảng điều khiển, vì vậy tôi nghĩ nó có thể là byte trống bẩn. Chỉ là lời giải thích cuối cùng - khoảng trắng thừa đó từ ReadString có thể là gì?
mark2222

Được rồi, tôi sẽ trả lời câu hỏi của riêng mình - đó là \ r rồi đến \ n: P Đầu ra của bảng điều khiển buồn cười là do tôi đã xuất \ r mà không có \ n.
mark2222

8
Xin lưu ý rằng phương pháp này sẽ không hoạt động với các chuỗi Unicode! groups.google.com/forum/#!msg/golang-nuts/ZeYei0IWrLg/…
Melllvar

@Melllvar Đó là lý do tại sao tôi sửa lại "nếu đó là một ký tự một byte" . Nếu bạn muốn loại bỏ một ký tự chiếm nhiều hơn một byte (đó không phải là trường hợp của OP), bạn phải điều chỉnh.
Denys Séguret

25

Các chuỗi Go không được kết thúc bằng null và để loại bỏ ký tự cuối cùng của một chuỗi, bạn chỉ cần thực hiện:

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

10
Điều này không chính xác và sẽ gây ra lỗi. Thao tác này loại bỏ byte cuối cùng khỏi chuỗi, điều này có thể làm cho nó không hợp lệ UTF-8 (hoặc mã hóa đa byte khác).
dr. Sybren

3
Xem play.golang.org/p/K3HBBtj4Oi để biết ví dụ về cách lỗi này xảy ra.
dr. Sybren

10

Để tránh hoang mang về đầu vào có độ dài bằng 0, hãy kết hợp thao tác cắt ngắn trong if

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

9

Đây là cách đơn giản để thực hiện chuỗi con trong 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

CẢNH BÁO: chỉ hoạt động trên chuỗi sẽ chỉ hoạt động với ASCII và sẽ đếm sai khi đầu vào là ký tự được mã hóa UTF-8 không phải ASCII và thậm chí có thể sẽ làm hỏng các ký tự vì nó cắt các ký tự nhiều byte ở giữa chuỗi.

Đây là phiên bản nhận biết 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
Điều này cần nhiều lượt ủng hộ hơn - tôi vừa bị cắn nặng khi không sử dụng tính năng tách nhận biết utf-8.
kolaente


2

8 năm sau, tôi tình cờ tìm thấy viên ngọc này, và tôi không tin rằng câu hỏi ban đầu của OP đã thực sự được trả lời:

vì vậy tôi đã nghĩ ra đoạn mã sau để cắt ký tự dòng mới

Trong khi bufio.Readerkiểu này hỗ trợ một ReadLine() phương thức vừa loại bỏ \r\nvừa \ncó nghĩa là một hàm cấp thấp, rất khó sử dụng vì cần phải kiểm tra nhiều lần.

IMO một cách thành ngữ để loại bỏ khoảng trắng là sử dụng thư viện chuỗi của 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)

Xem ví dụ này đang hoạt động trong sân chơi Golang: https://play.golang.org/p/HrOWH0kl3Ww

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.