短いバージョン: これは 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
}