Recherche de chaîne insensible à la casse dans golang

Comment puis-je rechercher un mot dans un fichier de manière insensible à la casse?

Par exemple

Si je recherche UpdaTe dans le fichier, si le fichier contient une mise à jour, la recherche doit le sélectionner et le Compter comme une correspondance.

21
demandé sur user7610 2014-07-19 06:00:57

4 réponses

strings.EqualFold() peut vérifier si deux chaînes sont égales, tout en ignorant la casse. Il fonctionne même avec Unicode. Voir http://golang.org/pkg/strings/#EqualFold pour plus d'informations.

Http://play.golang.org/p/KDdIi8c3Ar

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.EqualFold("HELLO", "hello"))
    fmt.Println(strings.EqualFold("ÑOÑO", "ñoño"))
}

Les deux renvoient true.

47
répondu 425nesp 2014-10-29 05:55:18

Vraisemblablement, la partie importante de votre question Est la recherche, pas la partie sur la lecture d'un fichier, donc je vais juste répondre à cette partie.

Le moyen le plus simple de le faire est probablement de convertir les deux chaînes (celle que vous recherchez et celle que vous recherchez) en majuscules ou en minuscules, puis de rechercher. Par exemple:

func CaseInsensitiveContains(s, substr string) bool {
    s, substr = strings.ToUpper(s), strings.ToUpper(substr)
    return strings.Contains(s, substr)
}

Comme Vous pouvez le voir en action ici.

12
répondu joshlf 2014-07-19 03:02:44

Si votre fichier est volumineux, vous pouvez utiliser regexp et bufio:

//create a regex `(?i)update` will match string contains "update" case insensitive
reg := regexp.MustCompile("(?i)update")
f, err := os.Open("test.txt")
if err != nil {
    log.Fatal(err)
}
defer f.Close()

//Do the match operation
//MatchReader function will scan entire file byte by byte until find the match
//use bufio here avoid load enter file into memory
println(reg.MatchReader(bufio.NewReader(f)))

À propos de bufio

Le paquet bufio implémente un lecteur tamponné qui peut être utile à la fois pour son efficacité avec beaucoup de petites lectures et en raison de la supplémentaire les méthodes de lecture qu'il offre.

5
répondu chendesheng 2014-07-19 13:44:44

N'utilisez pas strings.Contains sauf si vous avez besoin d'une correspondance exacte plutôt que de recherches de chaînes correctes dans la langue

Aucune des réponses actuelles n'est correcte à moins que vous ne cherchiez que des caractères ASCII la minorité de langues (comme l'anglais) sans certains diaeresis / umlauts ou autres modificateurs de glyphe unicode (la façon la plus "correcte" de la définir comme mentionné par @snap). La phrase standard de google est "recherche de caractères non ASCII".

Pour un soutien approprié pour recherche de langue que vous devez utiliser http://golang.org/x/text/search .

func SearchForString(str string, substr string) (int, int) {
    m := search.New(language.English, search.IgnoreCase)
    return = m.IndexString(str, substr)
}

start, end := SearchForString('foobar', 'bar');
if start != -1 && end != -1 {
    fmt.Println("found at", start, end);
}

, Ou si vous voulez juste l'indice de départ:

func SearchForStringIndex(str string, substr string) (int, bool) {
    m := search.New(language.English, search.IgnoreCase)
    start, _ := m.IndexString(str, substr)
    if start == -1 {
        return 0, false
    }
    return start, true
}

index, found := SearchForStringIndex('foobar', 'bar');
if found {
    fmt.Println("match starts at", index);
}

Recherche de l'language.Tag les structures ici pour trouver la langue que vous souhaitez rechercher avec ou utilisez language.Und si vous n'êtes pas sûr.

Mise à jour

Il semble y avoir une certaine confusion, donc cet exemple suivant devrait aider à clarifier les choses.

package main

import (
    "fmt"
    "strings"

    "golang.org/x/text/language"
    "golang.org/x/text/search"
)

var s = `Æ`
var s2 = `Ä`

func main() {
    m := search.New(language.Finnish, search.IgnoreDiacritics)
    fmt.Println(m.IndexString(s, s2))
    fmt.Println(CaseInsensitiveContains(s, s2))
}

// CaseInsensitiveContains in string
func CaseInsensitiveContains(s, substr string) bool {
    s, substr = strings.ToUpper(s), strings.ToUpper(substr)
    return strings.Contains(s, substr)
}
1
répondu Xeoncross 2017-03-27 01:28:44