Java 如何用多个分隔符拆分字符串-并知道哪个分隔符匹配

Java 如何用多个分隔符拆分字符串-并知道哪个分隔符匹配,java,regex,algorithm,string-parsing,string-split,Java,Regex,Algorithm,String Parsing,String Split,使用String.split可以很容易地用多个分隔符分割字符串。您只需要定义一个正则表达式,它匹配您想要使用的所有分隔符。比如说 "1.22-3".split("[.-]") 列表中的结果包含元素“1”、“22”和“3”。到目前为止还不错 但是现在我还需要知道在片段之间找到了哪一个分隔符。有没有一个简单的方法来实现这一点 我查看了String.split、其弃用的前身StringTokenizer,以及其他据信更为现代的库(例如),但没有它们,我就无法找到匹配的分隔符。我想我所看到的是错误的算

使用
String.split
可以很容易地用多个分隔符分割字符串。您只需要定义一个正则表达式,它匹配您想要使用的所有分隔符。比如说

"1.22-3".split("[.-]")
列表中的结果包含元素
“1”
“22”
“3”
。到目前为止还不错

但是现在我还需要知道在片段之间找到了哪一个分隔符。有没有一个简单的方法来实现这一点


我查看了
String.split
、其弃用的前身
StringTokenizer
,以及其他据信更为现代的库(例如),但没有它们,我就无法找到匹配的分隔符。

我想我所看到的是错误的算法。以下两步方法更为成功,而不是使用通过分隔符分割的方法:

  • 首先,我实现了一个将字符串拆分为包含分隔符的标记的方法。即将
    1.22-3
    分为
    1
    22
    -
    3

  • 然后,我实现了一个解析器来解释这个令牌流,即区分段及其分隔符


lexer的可能实现:

import java.util.ArrayList;
import java.util.List;

public final class FixedStringTokenScanner {

    /**
     * Splits the given input into tokens. Each token is either one of the given constant string
     * tokens or a string consisting of the other characters between the constant tokens.
     *
     * @param input
     *            The string to split.
     * @param fixedStringTokens
     *            A list of strings to be recognized as separate tokens.
     * @return A list of strings, which when concatenated would result in the input string.
     *         Occurrences of the fixed string tokens in the input string are returned as separate
     *         list entries. These entries are reference-equal to the respective fixedStringTokens
     *         entry. Characters which did not match any of the fixed string tokens are concatenated
     *         and returned as list entries at the respective positions in the list. The list does
     *         not contain empty or <code>null</code> entries.
     */
    public static List<String> splitToFixedStringTokensAndOtherTokens(final String input, final String... fixedStringTokens) {
        return new FixedStringTokenScannerRun(input, fixedStringTokens).splitToFixedStringAndOtherTokens();
    }

    private static class FixedStringTokenScannerRun {

        private final String input;
        private final String[] fixedStringTokens;

        private int scanIx = 0;
        StringBuilder otherContent = new StringBuilder();
        List<String> result = new ArrayList<String>();

        public FixedStringTokenScannerRun(final String input, final String[] fixedStringTokens) {
            this.input = input;
            this.fixedStringTokens = fixedStringTokens;
        }

        List<String> splitToFixedStringAndOtherTokens() {
            while (scanIx < input.length()) {
                scanIx += matchFixedStringOrAppendToOther();
            }
            storeOtherTokenIfNotEmpty();
            return result;
        }

        /**
         * @return the number of matched characters.
         */
        private int matchFixedStringOrAppendToOther() {
            for (String fixedString : fixedStringTokens) {
                if (input.regionMatches(scanIx, fixedString, 0, fixedString.length())) {
                    storeOtherTokenIfNotEmpty();
                    result.add(fixedString); // add string instance so that identity comparison works
                    return fixedString.length();
                }
            }
            appendCharacterToOther();
            return 1;
        }

        private void appendCharacterToOther() {
            otherContent.append(input.substring(scanIx, scanIx + 1));
        }

        private void storeOtherTokenIfNotEmpty() {
            if (otherContent.length() > 0) {
                result.add(otherContent.toString());
                otherContent.setLength(0);
            }
        }
    }
}

如果您回溯
String.split(regex)
所做的事情,并记录
String.split
忽略的信息,这非常简单:

String source = "1.22-3";
Matcher m=Pattern.compile("[.-]").matcher(source);
ArrayList<String> elements=new ArrayList<>();
ArrayList<String> separators=new ArrayList<>();
int pos;
for(pos=0; m.find(); pos=m.end()) {
    elements.add(source.substring(pos, m.start()));
    separators.add(m.group());
}
elements.add(source.substring(pos));
String source=“1.22-3”;
Matcher m=Pattern.compile(“[.-]”).Matcher(源代码);
ArrayList元素=新的ArrayList();
ArrayList分隔符=新的ArrayList();
int pos;
对于(pos=0;m.find();pos=m.end()){
添加(source.substring(pos,m.start());
分隔符。添加(m.group());
}
添加(源子字符串(pos));
在这段代码的末尾,
分隔符.get(x)
生成
元素.get(x)
元素.get(x+1)
之间的分隔符。应该清楚的是,
分隔符
元素
小一项


如果希望在一个列表中包含元素和分隔符,只需更改代码,使这两个列表成为同一个列表。这些项目已按发生顺序添加。

您自己的问题的答案??????/这也像它的smomebody一样?????我在这个问题上花了很长时间,只有在找到解决方案后,我才认为这个问题可能值得在这里提出。您可以用第一人称写出来mode@vks:如果它能让你快乐,我可以重写,以便清楚地知道我问了这个问题。尽管社区推荐了我最初的方法:很好!请注意:
elements
在这段代码中与
String.split的结果略有不同,因为它的末尾可能有一个空的String元素。代码不会忽略尾随分隔符。但是这是好的。解决这个问题很容易,但是对于大多数应用程序来说,保持不变的是,对于
x+1
元素,确实有
x
分隔符更有用。如果将两者都收集到一个列表中,那么允许列表以分隔符结尾就可以了。看起来保留分隔符的要求隐含地禁止忽略尾部分隔符,否则结果将不一致。