2

短いバージョン: これは 3 を出力します。Go では文字列は基本的にバイトのスライスであり、この文字を表すのに 3 バイトかかるため、これは理にかなっています。len および regexp 関数をバイト単位ではなく文字単位で機能させるにはどうすればよいですか。

package main
import "fmt"
func main() {
    fmt.Println(len("ウ"))//returns 3
    fmt.Println(utf8.RuneCountInString("ウ"))//returns 1
}

バックグラウンド:

JDO (Java) を使用してテキストを GAE データストアに保存しています。

次に、Go を使用してテキストを処理しています。具体的には、regexp.FindStringIndex を使用してインデックスをデータストアに保存しています。

次に、Java ランドに戻り、変更されていないテキストを送信し、json を介して GWT クライアントにインデックスを付けます。

途中のどこかでインデックスが「シフト」しているため、クライアント上にあるときまでにインデックスはオフになっています。

問題は文字エンコーディングに関係しているようです。Java/Go がテキスト (インデックス) を異なる方法で解釈していると仮定しています utf-8 char/byte?. regexp パッケージに Runes への参照があります。

go で regexp.FindStringIndex がバイト インデックスを返すようにするか、GWT クライアントに utf-8 インデックスを理解させることができると思います。

助言がありますか?将来的にアプリを国際化する必要がある場合に備えて、UTF-8 を使用する必要があります。

ありがとう

編集:

また、サーバーでJavaを使用してインデックスを見つけていたときも、うまくいきました。

クライアント(GWT)では、 text.substring(start,end) を使用しています

テスト:

package main

import "regexp"
import "fmt"

func main() {
    fmt.Print(regexp.MustCompile(`a`).FindStringIndex("ウィキa")[1])
}

コードは 4 ではなく 10 を出力します。

計画は、FindStringIndex が 4 を返すようにすることですが、何かアイデアはありますか?

更新 2: 位置の変換

func main() {
    s:="ab日aba本語ba";
    byteIndex:=regexp.MustCompile(`a`).FindAllStringIndex(s,-1)
    fmt.Println(byteIndex)//[[0 1] [5 6] [7 8] [15 16]]

    offset :=0
    posMap := make([]int,len(s))//maps byte-positions to char-positions
    for pos, char := range s {
        fmt.Printf("character %c starts at byte position %d, has an offset of %d, and a char position of %d.\n", char, pos,offset,pos-offset)
        posMap[pos]=offset
        offset += utf8.RuneLen(char)-1
    }
    fmt.Println("posMap =",posMap)
    for pos ,value:= range byteIndex{
        fmt.Printf("pos:%d value:%d subtract %d\n",pos,value,posMap[value[0]])
        value[1]-=posMap[value[0]]
        value[0]-=posMap[value[0]]
    }
    fmt.Println(byteIndex)//[[0 1] [3 4] [5 6] [9 10]]

}

* アップデート 2 *

    lastPos:=-1
    for pos, char := range s {
        offset +=pos-lastPos-1
        fmt.Printf("character %c starts at byte position %d, has an offset of %d, and a char position of %d.\n", char, pos,offset,pos-offset)
        posMap[pos]=offset
        lastPos=pos
    }
4

1 に答える 1

4

おそらくご存じのとおり、Go と Java では文字列の扱いが異なります。Java では、文字列は一連のコードポイント (文字) です。Go では、文字列は一連のバイトです。Go のテキスト操作関数は、必要に応じて UTF-8 コードポイントを理解しますが、文字列はバイトとして表されるため、関数が返し、操作するインデックスは、文字インデックスではなくバイト インデックスです。

コメントでわかるように、RuneReaderandを使用してFindReaderIndex、バイトではなく文字でインデックスを取得できます。strings.Readerは の実装を提供するRuneReaderため、 を使用strings.NewReaderして文字列をRuneReader.

もう 1 つのオプションは、必要な文字数の部分文字列を取得し、UTF-8 文字列の文字数を返すutf8.RuneLenに渡すことです。ただし、 a を使用するRuneReader方がおそらく効率的です。

于 2012-04-13T01:14:30.407 に答える