Подтвердить что ты не робот

Нечувствительный к регистру поиск строки в golang

Как выполнить поиск в файле для слова без учета регистра?

Например

Если я ищу UpdaTe в файле, если файл содержит обновление, поиск должен выбрать его и считать в качестве соответствия.

4b9b3361

Ответ 1

strings.EqualFold() может проверить, равны ли две строки, игнорируя регистр. Он работает даже с Unicode. Подробнее см. http://golang.org/pkg/strings/#EqualFold.

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"))
}

Оба возвращают true.

Ответ 2

Предположительно, важной частью вашего вопроса является поиск, а не часть чтения из файла, поэтому я просто отвечу на эту часть.

Вероятно, самый простой способ сделать это - конвертировать обе строки (ту, которую вы ищите, и ту, что вы ищете) во весь верхний регистр или все в нижнем регистре, а затем выполнить поиск. Например:

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

Вы можете увидеть его в действии здесь.

Ответ 3

Если ваш файл большой, вы можете использовать regexp и 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)))

О bufio

В пакет bufio реализован буферный считыватель, который может быть полезен как за его эффективность с большим количеством мелких чтений и из-за дополнительного которые он предоставляет.

Ответ 4

Не используйте strings.Contains, если вам не нужны точные соответствия, а не правильные строки поиска по строке

Ни один из текущих ответов не является правильным, если вы не только ищете ASCII-символы меньшинство языков (например, английский) без определенных diaeresis/умляутов или других модификаторов глифов Unicode (чем больше "правильный" способ определите его, как указано @snap). Стандартная фраза google - "поиск не-ASCII-символов".

Для правильной поддержки поиска языка вам необходимо использовать 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);
}

Или, если вам просто нужен начальный индекс:

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);
}

Найдите language.Tag structs here, чтобы найти язык, который вы хотите найти, или используйте language.Und, если вы не уверены.

Update

Кажется, есть некоторая путаница, поэтому следующий пример должен помочь прояснить ситуацию.

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)
}