Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java字符串标记化:按模式拆分和保留模式_Java_Regex_String_Scala_Tokenize - Fatal编程技术网

Java字符串标记化:按模式拆分和保留模式

Java字符串标记化:按模式拆分和保留模式,java,regex,string,scala,tokenize,Java,Regex,String,Scala,Tokenize,我的问题是Python上查询的Scala(Java)变体 特别是,我有一个字符串val myStr=“我们可以在上午8:45见面吗?”。我希望将其标记化并保留分隔符(除空格外的所有分隔符)。如果我的分隔符仅为字符,例如,:,?等,我可以执行以下操作: val strArr=myStr.split(((\\s+)|(?=[,.;:?]))|(?我建议匹配所有标记,而不是拆分字符串,因为这样您可以更好地控制所获得的内容: \b\d{1,2}:\d{2}\b|[,.;:?]+|(?:(?!\b\d{

我的问题是Python上查询的Scala(Java)变体

特别是,我有一个字符串
val myStr=“我们可以在上午8:45见面吗?”
。我希望将其标记化并保留分隔符(除空格外的所有分隔符)。如果我的分隔符仅为字符,例如
等,我可以执行以下操作:


val strArr=myStr.split(((\\s+)|(?=[,.;:?]))|(?我建议匹配所有标记,而不是拆分字符串,因为这样您可以更好地控制所获得的内容:

 \b\d{1,2}:\d{2}\b|[,.;:?]+|(?:(?!\b\d{1,2}:\d{2}\b)[^\s,.;:?])+

我们开始匹配最具体的模式,最后一个是最通用的模式

详细信息

  • \b\d{1,2}:\d{2}\b
    -1到2个数字,
    ,2个用单词边界括起来的数字
  • |
    -或
  • [,.;:?]+
    -1个或多个
    字符
  • |
    -或
  • (?:(?!\b\d{1,2}:\d{2}\b)[^\s,.;:?])+
    -匹配任何不是分隔符字符的字符或不是时间字符串起点的空白(
    [^\s,.;:?])
考虑:

输出:

Shall
we
meet
at
,
let's
say
,
8:45
AM
?
/**
*StringPatternTokenizer与java.util.StringTokenizer类似
*但它使用regex字符串作为标记器分隔符。
*有关详细用法,请参见内部方法#testCase。
*/
公共类StringPatternTokenizer{
模式;
公共StringPatternTokenizer(字符串正则表达式){
this.pattern=pattern.compile(regex);
}
公共void getTokens(字符串str,NextToken-NextToken){
Matcher-Matcher=pattern.Matcher(str);
int指数=0;
结果=空;
while(matcher.find()){
if(matcher.start()>索引){
result=nextToken.visit(null,str.substring(index,matcher.start());
}
if(result!=result.STOP){
index=matcher.end();
结果=nextToken.visit(匹配器,空);
}
if(result==result.STOP){
返回;
}
}
如果(索引{
sb.append(matcher==null?str
:data.optString(matcher.group(1),“”);
返回StringPatternTokenizer.Result.CONTINUE;
});
//按预期检查结果
Assert.assertEquals(strTarget,sb.toString());
}
}

你有机会检查我的方法吗?是的,我已经检查了到目前为止提到的两种方法。我只是在我拥有的更通用的示例上进行了尝试。很好,请注意我的方法匹配1)时间子字符串作为整词,或2)分隔符字符的任何块,或3)任何不是你的定界符和时间字符串的词。我相信它足够全面,可以按照你需要的方式标记字符串。请注意
\d{1,2}:\d{2}如果您只想在任何上下文中匹配1-2位数字的序列,
,2位数字,则可以删除。
。我的查询只是我拥有的大量用例中的一个示例。您的解决方案扩展到任意模式。例如,我可以为电子邮件地址、日期、时间戳等指定模式字符串,并将它们连接在一起.Thank.Code-only答案不如Code-with-explaining有用。特别是在回答这么老的问题时,指出你的答案与公认答案的不同之处/原因是很有帮助的。
Shall
we
meet
at
,
let's
say
,
8:45
AM
?
/**
 * StringPatternTokenizer is simlular to java.util.StringTokenizer
 * But it uses regex string as the tokenizer separator.
 * See inside method #testCase for detail usage.
 */
public class StringPatternTokenizer {
    Pattern pattern;

    public StringPatternTokenizer(String regex) {
        this.pattern = Pattern.compile(regex);
    }

    public void getTokens(String str, NextToken nextToken) {
        Matcher matcher = pattern.matcher(str);

        int index = 0;
        Result result = null;
        while (matcher.find()) {
            if (matcher.start() > index) {
                result = nextToken.visit(null, str.substring(index, matcher.start()));
            }
            if (result != Result.STOP) {
                index = matcher.end();
                result = nextToken.visit(matcher, null);
            }

            if (result == Result.STOP) {
                return;
            }
        }

        if (index < str.length()) {
            nextToken.visit(null, str.substring(index));
        }
    }

    enum Result {
        CONTINUE,
        STOP,
    }

    public interface NextToken {
        Result visit(Matcher matcher, String str);
    }

    /***********************************/
    /***** test cases FOR IT ***********/
    /***********************************/

    public void testCase() {

        // as a test, it tries access tokenizer result for each part,
        // then replace variable parts by given values.
        // And finally, we collect the result target string as  output.

        String strSource = "My name is {{NAME}}, nice to meet you.";
        String strTarget = "My name is TokenTst, nice to meet you.";

        // separator pattern for: variable names in two curly brackets
        String variableRegex = "\\{\\{([A-Za-z]+)\\}\\}";

        // variable values
        org.json.JSONObject data = new org.json.JSONObject(
                java.util.Collections.singletonMap("NAME", "TokenTst")
        );

        StringBuilder sb = new StringBuilder();
        new StringPatternTokenizer(variableRegex)
                .getTokens(strSource, (matcher, str) -> {
                    sb.append(matcher == null ? str
                            : data.optString(matcher.group(1), ""));
                    return StringPatternTokenizer.Result.CONTINUE;
                });

        // check the result as expected
        org.junit.Assert.assertEquals(strTarget, sb.toString());
    }
}