使用Scanner.useDelimiter()时,正则表达式会导致额外的空格。

3
我正在尝试使用Scanner从用户输入读取文本文件,并使用特定情况下进行单词分隔符的分隔。其中一个情况是当单词在开头或结尾具有撇号时必须进行分隔,但不应影响单词内的撇号。例如:如果scanner看到像“'tis”这样的单词,则scanner.useDelimiter()应该能够去掉撇号并保留单词“tis”,但是如果它看到像“don't”这样的单词,则应该将单词保留为原样。
我正在使用正则表达式来覆盖分隔符应按其进行分隔的多个情况。正则表达式正在做我需要的事情,但由于某种原因,我的结果在具有空格和单词前面的撇号的单词之前会打印出额外的空格。我对正则表达式不熟悉,不知道如何解决这个问题,但是非常感谢任何建议。
以下是我的文本文件中的单词:
'Twas the night before christmas! But don't open your presents. 'Tis the only way to celebrate.
代码:
  public static void main (String[] args){
      Pattern p = Pattern.compile("[\\p{Punct}\\s&&[^']]+|('(?![\\w]))+|((?<![\\w])')+");
      System.out.println("Please enter a text file name.");
        
      Scanner sc = new Scanner(System.in);
        
      File file = new File(sc.nextLine());
        
      Scanner nSc = new Scanner(file);
        
      nSc.useDelimiter(p);
        
      while (nSc.hasNext()){
        
         String word = nSc.next().toLowerCase();
         System.out.println(word);
       
      }
      nSc.close();
}

期望值:

twas 
the 
night 
before 
christmas 
but 
don't 
open 
your 
presents 
tis 
the 
only 
way 
to 
celebrate

实际:

twas 
the 
night 
before 
christmas 
but 
don't 
open 
your 
presents

tis 
the 
only 
way 
to 
celebrate

1
你为什么要从'twas和'tis中删除',当'在don't中具有完全相同的作用? - NomadMaker
1
在“don't”中,撇号代替了字母“o”。在“'twas”中,撇号代替了字母“i”。 - NomadMaker
1个回答

1
你可以使用 正则表达式, '?\b\w+'?\w+\b 从字符串中获取所需的单词,然后将正则表达式 '(.*) 替换为 $1,其中 $1 指定 group(1)
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        String str = "'Twas the night before christmas! But don't open your presents. 'Tis the only way to celebrate.";
        List<String> list = Pattern.compile("'?\\b\\w+'?\\w+\\b")
                .matcher(str)
                .results()
                .map(r->r.group().replaceAll("'(.*)", "$1"))
                .collect(Collectors.toList());

        System.out.println(list);
    }
}

输出:

[Twas, the, night, before, christmas, But, dont, open, your, presents, Tis, the, only, way, to, celebrate]

正则表达式 '?\b\w+'?\w+\b 的解释:

  1. \b 指定了单词边界
  2. \w+ 指定了一个或多个 单词字符
  3. '? 指定了可选的 '

如果您不熟悉 Stream API,可以按照以下方式进行操作:

Scanner nSc = new Scanner(file);
while (nSc.hasNextLine()) {
    String line = nSc.nextLine().toLowerCase();
    Pattern pattern = Pattern.compile("'?\\b\\w+'?\\w+\\b");
    Matcher matcher = pattern.matcher(line);
    while (matcher.find()) {
        String word = matcher.group();
        System.out.println(word.replaceAll("'(.*)", "$1"));
    }
}
nSc.close();

谢谢您的帮助,这基本上是我想要的,但我仍然需要保留那些前面有撇号的单词。因此像“'twas”这样的单词将变成“twas”。 - ssang
@ssang - 我已根据这个澄清更新了答案。如有任何疑问/问题,请随时发表评论。 - Arvind Kumar Avinash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接