Разделение строки на пробелы, если только в двойных кавычках, кроме двойных кавычек, не может быть прикреплена предшествующая строка - PullRequest
0 голосов
/ 03 мая 2018

Мне нужно разбить строку в Java (сначала удалите пробелы между кавычками, а затем разбейте пробелы.)

"abc test = \" x y z \ "magic = \" hello \ "hola"

становится:

во-первых:

"abc test = \" xyz \ "magic = \" hello \ "hola"

, а затем:

  • а
  • тест = "хуг"
  • магия = "привет"
  • Голя

Сценарий: Я получаю строку, похожую на приведенную выше, из ввода, и я хочу разбить ее на части, как указано выше. Один из подходов - сначала убрать пробелы между кавычками, а затем разбить пробелы. Также строка перед кавычками усложняет это. Второй был разделен пробелами, но не внутри кавычек, а затем удалил пробелы из отдельных разбиений. Я пытался захватить кавычки с помощью "\" ([^ \ "] +) \" ", но я не могу захватить только пробелы внутри кавычек. Я попробовал еще немного, но не повезло.

Ответы [ 4 ]

0 голосов
/ 03 мая 2018

Звучит так, будто вы хотите написать базовый парсер / токенизатор. Бьюсь об заклад, что после того, как вы сделаете что-то, что может иметь дело с красивой печатью в этой структуре, вы скоро захотите начать проверять, нет ли несовпадений ".

Но, по сути, у вас есть несколько этапов для решения этой конкретной проблемы, а в Java есть встроенный токенизатор, который может оказаться полезным.

import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

public class Q50151376{

    private static class Whitespace{
        Whitespace(){ }
        @Override
        public String toString() {
            return "\n";
        }
    }

    private static class QuotedString {
        public final String string;

        QuotedString(String string) {
            this.string = "\"" + string.trim() + "\"";
        }

        @Override
        public String toString() {
            return string;
        }
    }

    public static void main(String[] args) {
        String test = "abc test=\"x y z\" magic=\" hello \" hola";
        StringTokenizer tokenizer = new StringTokenizer(test, "\"");
        boolean inQuotes = false;
        List<Object> out = new LinkedList<>();
        while (tokenizer.hasMoreTokens()) {
            final String token = tokenizer.nextToken();
            if (inQuotes) {
                out.add(new QuotedString(token));
            } else {
                out.addAll(TokenizeWhitespace(token));
            }
            inQuotes = !inQuotes;
        }

        System.out.println(joinAsStrings(out));
    }

    private static String joinAsStrings(List<Object> out) {
        return out.stream()
                .map(Object::toString)
                .collect(Collectors.joining());
    }

    public static List<Object> TokenizeWhitespace(String in){
        List<Object> out = new LinkedList<>();
        StringTokenizer tokenizer = new StringTokenizer(in, " ", true);

        boolean ignoreWhitespace = false;
        while (tokenizer.hasMoreTokens()){
            String token = tokenizer.nextToken();
            boolean whitespace = token.equals(" ");
            if(!whitespace){
                out.add(token);
                ignoreWhitespace = false;
            } else if(!ignoreWhitespace) {
                out.add(new Whitespace());
                ignoreWhitespace = true;
            }
        }
        return out;
    }

}
0 голосов
/ 03 мая 2018

Возможно, другой ответ лучше, но я все же написал его, поэтому я опубликую его здесь;) Он использует другой подход

public static void main(String[] args) {
        String test="abc test=\"x y z\"   magic=\"  hello   \"   hola";
          Pattern pattern = Pattern.compile("([^\\\"]+=\\\"[^\\\"]+\\\" )");
            Matcher matcher = pattern.matcher(test);
            int lastIndex=0;
            while(matcher.find()) {
                String[] parts=matcher.group(0).trim().split("=");

                boolean newLine=false;
                for (String string : parts[0].split("\\s+")) {
                    if(newLine)
                        System.out.println();
                    newLine=true;
                    System.out.print(string);
                }
                System.out.println("="+parts[1].replaceAll("\\s",""));
                lastIndex=matcher.end();
            }
            System.out.println(test.substring(lastIndex).trim());           
    }

Результат

abc
test="xyz"
magic="hello"
hola
0 голосов
/ 03 мая 2018

Я хотел бы упомянуть java 9's Matcher.replaceAll лямбда-расширение:

// Find quoted strings and remove there whitespace:
s = Pattern.compile("\"[^\"]*\"").matcher(s)
    .replaceAll(mr -> mr.group().replaceAll("\\s", ""));

// Turn the remaining whitespace in a comma and brace all.
s = '{' + s.trim().replaceAll("\\s+", ", ") + '}';
0 голосов
/ 03 мая 2018

Мы можем сделать это используя формальное сопоставление с образцом. Секретный ответ ответа ниже состоит в том, чтобы использовать не очень используемый метод Matcher#appendReplacement. Мы делаем паузу в каждом совпадении, а затем добавляем произвольную замену всего, что появляется внутри двух пар кавычек. Пользовательский метод removeSpaces() удаляет все пробелы из каждого цитируемого термина.

public static String removeSpaces(String input) {
    return input.replaceAll("\\s+", "");
}

String input = "abc test=\"x y z\" magic=\" hello \" hola";
Pattern p = Pattern.compile("\"(.*?)\"");
Matcher m = p.matcher(input);
StringBuffer sb = new StringBuffer("");
while (m.find()) {
    m.appendReplacement(sb, "\"" + removeSpaces(m.group(1)) + "\"");
}
m.appendTail(sb);

String[] parts = sb.toString().split("\\s+");
for (String part : parts) {
    System.out.println(part);
}

abc
test="xyz"
magic="hello"
hola

Демо

Большое предостережение, как намекают вышеупомянутые комментарии, заключается в том, что мы действительно используем движок регулярных выражений в качестве элементарного синтаксического анализатора. Чтобы увидеть, где мое решение быстро не сработает, просто удалите одну из цитат случайно из цитируемого термина. Но если вы уверены, что ваш вклад правильно сформирован, как вы показали нам, этот ответ может сработать для вас.

...