【问题标题】:Split a list on spaces and group quoted characters拆分空格列表并分组引用字符
【发布时间】:2022-01-06 11:06:51
【问题描述】:

我正在尝试将输入字符串解析为标记,其中每个标记都是字符串中的一个单词。 但是,我也希望标记能够包含空格,并且为了更清晰的语法,我希望能够在标记的中间出现引号,并且能够转义引号 (\")

示例输入字符串和我想要的输出(从输出中删除引号以表示字符串以提高可读性):

  • 输入:diamond_sword name:"test name" -> 输出:[diamond_sword, name:test name]
  • 输入:stick 1 name:"The \"Holy\" Stick" -> 输出:[stick, 1, name:The "Holy" Stick]

我不希望引号必须与其他单词 (name:"string") 分开,而不是做许多其他人在以前的问题中提出的问题,我只希望 转义 引号保留,删除所有未转义的引号。

这可能吗?以这种方式将字符串变成列表会是什么样子?

【问题讨论】:

  • Java 有内置类StreamTokenizer,它支持所描述的语法,尽管使用起来感觉有些笨拙,因为必须为每一轮解析单独设置语法规则。
  • @Izruo 我将如何使用流标记器来完成此任务?以前从未听说过它们,我不知道从哪里开始
  • 我做了一些研究:似乎StreamTokenizeris in the process of being deprecated。因此,我建议改用手动方法。

标签: java string minecraft


【解决方案1】:

也许是这样的?

import java.util.*;

public class Demo {
    private static List<String> parse(String in) {
        Objects.requireNonNull(in);
        char[] chars = in.toCharArray();
        var words = new ArrayList<String>();
        var sb = new StringBuilder();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == ' ') {
                // Space; add the current token to the result array.
                words.add(sb.toString());
                sb.setLength(0);
            } else if (chars[i] == '"') {
                // Iterate until the next unescaped quote
                // (Assumes strings are well-formatted; a more robust version
                //  wouldn't and would better handle error cases)
                for (i++; chars[i] != '"'; i++) {
                    // If current character is a backslash, skip and append
                    // the next
                    if (chars[i] == '\\') {
                        i++;
                    }
                    sb.append(chars[i]);
                }
            } else {
                sb.append(chars[i]);
            }
        }
        words.add(sb.toString()); // Don't forget the final token
        return words;
    }

    public static void main(String[] args) {
        List<String> strings =
            List.of("diamond_sword name:\"test name\"",
                    "stick 1 name:\"The \\\"Holy\\\" Stick\"");

        for (String s : strings) {
            List<String> words = parse(s);
            System.out.println(words);
        }
    }
}

编译并运行时,打印出来

[diamond_sword, name:test name]
[stick, 1, name:The "Holy" Stick]

【讨论】:

  • 正是我想要的,非常感谢!
猜你喜欢
  • 2017-08-11
  • 1970-01-01
  • 1970-01-01
  • 2022-12-26
  • 1970-01-01
  • 2014-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多