【问题标题】:Tokenize Words separated by non-word characters exept single quote标记由非单词字符分隔的单词,单引号除外
【发布时间】:2020-04-18 15:07:11
【问题描述】:

我尝试实现以下方法:将输入解析为“单词标记”:由非单词字符分隔的单词字符序列。但是,如果非单词字符被引用(在单引号中),它们可以成为标记的一部分。
我想使用正则表达式,但无法正确编写代码:

public static List<String> wordTokenize(String input) {
    Pattern pattern = Pattern.compile ("\\b(?:(?<=\')[^\']*(?=\')|\\w+)\\b");
    Matcher matcher = pattern.matcher (input);
    ArrayList ans = new ArrayList();
    while (matcher.find ()){
        ans.add (matcher.group ());
    }
    return ans;
}

我的正则表达式无法识别在没有空格的单词中间开始一个单词并不意味着开始一个新单词。例子:

  1. 输入:this-string '只有三个标记' // 有效

  2. 输入: "this*string'只有两个@tokens'"
    预期:[这个,字符串只有两个@tokens]
    实际:[this, string, 只有两个@tokens]

  3. 输入:“一'二''三'''四'二十一'”
    预期:[onetwothree, , 四, 二十一]
    实际:[一、二、三、四、二十一]

如何修复空格?

【问题讨论】:

  • 也许尝试用 \\w 切换?更多地关注“词”
  • 我更喜欢专注于我的解决方案,而不是从头开始一个解决方案
  • @ 是一个非单词字符,所以我不明白你在第二种情况下的预期输出。
  • 因为它在' '里面,不分开也没关系。问题是它分隔了单词中间没有空格且没有特殊字符的东西

标签: java regex tokenize


【解决方案1】:

您希望匹配最接近的单个直撇号之间出现的一个或多个单词 char 或子字符串,并从标记中删除所有这些撇号。

在匹配项上使用以下正则表达式和.replace("'", "")

(?:\w|'[^']*')+

请参阅regex demo。详情:

  • (?: - 非捕获组的开始
    • \w - 一个字字符
    • | - 或
    • ' - 单引号
    • [^']* - 除单引号外的任何 0+ 个字符
    • ' - 单引号
  • )+ - 组结束,出现 1 次以上。

Java demo

// String s = "this*string'has only two@tokens'"; // => [this, stringhas only two@tokens]
String s = "one'two''three' '' four 'twenty-one'"; // => [onetwothree, , four, twenty-one]
Pattern pattern = Pattern.compile("(?:\\w|'[^']*')+", Pattern.UNICODE_CHARACTER_CLASS);
Matcher matcher = pattern.matcher(s);
List<String> tokens = new ArrayList<>();
while (matcher.find()){
    tokens.add(matcher.group(0).replace("'", "")); 
}

注意 Pattern.UNICODE_CHARACTER_CLASS 是为 \w 模式添加的,以匹配所有 Unicode 字母和数字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-09
    • 1970-01-01
    • 2013-07-29
    • 2011-11-29
    • 2015-11-09
    • 1970-01-01
    相关资源
    最近更新 更多