【问题标题】:Czech characters in regexp search正则表达式搜索中的捷克语字符
【发布时间】:2021-11-30 03:46:59
【问题描述】:

我正在尝试为捷克语单词实现非常简单的文本匹配器。由于捷克语的后缀很重,我想定义单词的开头,然后贪婪地匹配单词的其余部分。这是我目前的实现:

    r := regexp.MustCompile("(?i)\\by\\w+\\b")
    text := "x yž z"
    matches := r.FindAllString(text, -1)
    fmt.Println(matches) //have [], want [yž]

我研究了 Go 的正则表达式语法: https://github.com/google/re2/wiki/Syntax

但我不知道,如何定义捷克语字符?使用 \w 只匹配 ASCII 字符,而不是捷克 UTF 字符。

你能帮帮我吗?

【问题讨论】:

  • 您的意思是您只需要搜索开头带有yY 的单词吗?还是您需要更灵活的解决方案?
  • 是的,在这个例子中是的。在更真实的例子中,我想匹配“uhličitá”、“uhličité”、“uhličitou”、“uhličitého”...
  • @Ondra 比正则表达式更接近全文搜索匹配。 FTS 引擎可以匹配基于词干和语言语法的所有形式。另一方面,前缀搜索会产生次优(有时是有趣)的结果,尤其是在使用复合词时。或前缀。您应该考虑使用 FTS 引擎。 Elastic 提供了多个language analyzers,包括捷克语
  • 有时正则表达式不是正确的工具。

标签: regex go


【解决方案1】:

在 RE2 中,\w\b 都是 not Unicode-aware

\b 位于 ASCII 字边界(一侧为“\w”,另一侧为“\W”、“\A”或“\z”)
\w 字字符(== [0-9A-Za-z_])

一个更通用的示例是用一个或多个非字母字符的任意块进行拆分,然后仅收集符合您条件的那些项目:

package main

import (
    "fmt"
    "strings"
    "regexp"
)

func main() {
    output := []string{}
    r := regexp.MustCompile(`\P{L}+`)
    str := "x--++yž,,,.z..00"
    words := r.Split(str, -1)
    for i := range words {
        if len(words[i]) > 0 && (strings.HasPrefix(words[i], `y`) || (strings.HasPrefix(words[i], `Y`)) {
            output = append(output, words[i])
        }
    }
    fmt.Println(output)
}

请参阅Go demo

请注意,像

这样的幼稚方法
package main

import (
    "fmt"
    "regexp"
)

func main() {
    output := []string{}
    r := regexp.MustCompile(`(?i)(?:\P{L}|^)(y\p{L}*)(?:\P{L}|$)`)
    str := "x--++yž,,,.z..00..."
    matches := r.FindAllStringSubmatch(str, -1)
    for _, v := range matches {
        output = append(output, v[1])
    }
    fmt.Println(output)
}

won't work 以防你在字符串中有 match1,match2 match3 之类的 consecutive 匹配项,因为它只会获取奇数事件,因为最后一个非捕获组模式将消耗应该的字符在下一次匹配时被第一个非捕获组模式匹配。

上述代码的解决方法是在非字母条纹的末尾添加一些非字母字符

package main

import (
    "fmt"
    "regexp"
)

func main() {
    output := []string{}
    r := regexp.MustCompile(`(?i)(?:\P{L}|^)(u\p{L}*)(?:\P{L}|$)`)
    str := "uhličitá,uhličité,uhličitou,uhličitého,yz,my"
    matches := r.FindAllStringSubmatch(regexp.MustCompile(`\P{L}+`).ReplaceAllString(str, `$0 `), -1)
    for _, v := range matches {
        output = append(output, v[1])
    }
    fmt.Println(output)
}
// => [uhličitá uhličité uhličitou uhličitého]

this Go demo

这里,regexp.MustCompile(`\P{L}+`).ReplaceAllString(str, `$0 `) 在所有非字母字符块之后添加一个空格。

【讨论】:

  • 我知道 Go 存在一些漏洞,但始终牢记泛型和编译器之类的东西。在正则表达式中混合 ASCII 和 Unicode 是....非常不幸
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-23
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
  • 2017-04-11
相关资源
最近更新 更多