Goで部分文字列を抽出する


114

コンソールから行全体(空白を含む)を読み取って処理しようとしています。bufio.ReadStringを使用すると、改行文字が入力と一緒に読み取られるため、改行文字をトリミングするために次のコードを考え出しました。

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

これを行うためのより慣用的な方法はありますか?つまり、部分文字列を抽出するときに、最後のnullバイトを処理するライブラリがすでにありますか?

(はい、go readline-> stringで改行文字のない行を読み取る方法がすでにあることは知っていますが、エレガントな文字列操作をもっと探しています。)

回答:


146

スライスの操作と文字列ストレージ形式に混乱しているようですが、これはCで使用しているものとは異なります。

  • Goのスライスには長さ(バイト単位)が格納されるため、len操作のコストを気にする必要はありません。カウントする必要はありません。
  • Go文字列はnullで終了しないため、nullバイトを削除する必要はなく1、スライス後に空の文字列を追加して追加する必要もありません。

最後の文字(1バイト文字の場合)を削除するには、次のようにします。

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

11
0(または:)も必要ありs = s[:len(s)-1]ません。
uriel

1
明確にしていただきありがとうございます。ReadString関数から返された文字列の最後に2つの空白文字があったようです。そのため、1つをnullバイトと間違えました。C文字列との混同でごめんなさい。fmtをbufioと一緒に使用していたため、コンソールに面白いものが表示されたため、ダーティnullバイトである可能性があると思いました。最後の説明ですが、ReadStringの余分な空白は何でしょうか
mark2222 2012

OK私は自分の質問に答えます-それは\ r次に\ nです:Pおかしいコンソール出力は、\ nなしで\ rを出力したためです。
mark2222 2012

8
このメソッドはUnicode文字列では機能しないことに注意してください!groups.google.com/forum/#!msg/golang-nuts/ZeYei0IWrLg/...
Melllvar

@Melllvarそれが私が「1バイト文字の場合」を正確にした理由です。1バイトを超えるcharを削除したい場合(OPの場合ではありません)、適応する必要があります。
DenysSéguret2013

25

Go文字列はnullで終了していません。文字列の最後の文字を削除するには、次のようにします。

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

10
これは正しくなく、バグの原因になります。これにより、文字列から最後のバイトが削除され、UTF-8(または他のマルチバイトエンコーディング)が無効になる可能性があります。
dr。シブレン2017年

3
これがどのように壊れるかの例については、play.golang.org / p / K3HBBtj4Oiを参照してください。
dr。シブレン

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対応の分割を使用しないことでひどく噛まれました。
kolaente


2

8年後、私はこの宝石を偶然見つけましたが、OPの元の質問が本当に答えられたとは思いません。

だから私は改行文字をトリミングするために次のコードを思いつきました

ながらbufio.ReaderタイプがサポートするReadLine() 方法を削除したの両方\r\n\n、それを繰り返しチェックが必要であるため、使用に不便であり、低レベルの関数として意図されています。

IMOで空白を削除する慣用的な方法は、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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.