Анализ аргументов командной строки, которые могут содержать пробелы

Я создаю утилиту командной строки на основе весенней загрузки, написанную на Java, для команд в моей организации. Мне придется разрешить командам передавать произвольные аргументы командной строки, которые могут содержать пробелы.

Я пытался найти какие-либо сторонние библиотеки или библиотеки Spring, которые могут это сделать, но я не смог найти ни одной, которая могла бы анализировать аргументы так, как я хочу.

java -jar client.jar --args='a=Car b=Truck c = "Car faster than Truck" d = "Car faster than all"'

В моей утилите командной строки я хотел бы получить аргументы.

a=Car
b=Truck
c=Car faster than Truck
d=Car faster than all

Я попробовал использовать регулярное выражение для разделения по пробелам, и, как вы понимаете, это не сработало. Я думаю, что разделение его по пробелам тоже не сработает.

Каким будет эффективный способ анализа этих аргументов?

«как вы понимаете, это не сработает» — Как бы мне это сказать?

Scott Hunter 08.08.2024 18:17

может ли ввод быть чем-то вроде java -jar client.jar a=Car b=Truck "c=Car faster than Truck" "d=Car faster than all" - это будет использовать естественное поведение (большинства) оболочки и приведет к args[0] = "a=Car", args[1] = "b=Truck", args[2] = "c=Car faster than Truck", args[3] = "d=Car fasater than all"

user85421 08.08.2024 18:25

Посмотрите проект Spring Shell

J Asgarov 08.08.2024 18:43

@user85421 user85421 Проект командной строки весенней загрузки не будет работать таким образом, потому что я думаю, что для получения его значения требуется имя параметра.

Haunted 08.08.2024 19:39

Говоря о командной строке, вам необходимо учитывать правила кавычек и экранирования оболочки, которую вы используете в своей ОС. Вы используете Windows cmd, powershell, bash, zsh или что-то еще? Они могут по-разному понимать кавычки, двойные кавычки и пробелы.

aled 08.08.2024 20:04

@aled Я использую bash.

Haunted 08.08.2024 20:10
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я ничего не знаю о Spring-Boot, но рискну предположить, что командная строка во многом похожа на все остальное. Общая цель здесь — разделить строку командной строки на основе пробелов, но не в двойных кавычках. Вы можете сделать это с помощью регулярного выражения, используя выражение Positive Lookahead и метод String#split(). Ниже приведен простой пример (обязательно прочитайте комментарии в коде):

/* Splits the supplied command-line string based on one (or more) 
   whitespace(s) but, not those that are contained within double 
   quote marks. This utilizes a Positive Lookahead regular expression
   for the String#split() method. If you want an explanation of 
   the regex used below, then copy/Paste: 
            \s{1,}(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)
   into the Regular Expression bar in https://regex101.com/      */
String argsString = "'a=Car b=Truck c=\"Car faster than Truck\"  d=\"Car faster than all\"'";
    
String regex = "\\s{1,}(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)";
    
/* Not exactly sure if the single quotes at the beginnind and end 
   of of the overall command-line is actually delivered, so the `if` 
   block below removes them. If they are not part of the overall 
   command-line string then you can just delete this `if` block. */
if (argsString.startsWith("'") && argsString.endsWith("'")) {
    argsString = argsString.substring(1, argsString.length() - 1);
}
    
// Create an array of the provided command-line arguments:
String[] args = argsString.split(regex, -1);
    
/* If you want, remove the double-quote marks from tag values 
   within command-line elements:        */
for (int i = 0; i < args.length; i++) {
    /* Done this way in case there are nested double-quote marks
       (for whatever reason) within the command line Tag Values.
       nested double-quote marks are NOT parsed out: */
    String[] tmp = args[i].split(" = ");
    if (tmp[1].startsWith("\"") && tmp[1].endsWith("\"")) {
        args[i] = tmp[0] + " = " + tmp[1].substring(1, tmp[1].length() - 1);
    }
}
    
// Display the command-line elements within the console window:
for (String str : args) {
    System.out.println(str);
}
    
System.out.println();
    
/* Further parsing would be to split each arg element 
   based on the " = " character:         */
System.out.println("Tag/Value Delimiter:    = ");
StringBuilder sb = new StringBuilder("");
for (String arg : args) {
    String[] elements = arg.split(" = ");
    sb.append(String.format(
              "Argument Tag: -> %-5s Argument Value: -> %-25s%n", 
              elements[0], elements[1]
            ));
}
System.out.println(sb.toString());

Если этот код задан, вы должны увидеть что-то вроде того, что показано ниже в окне консоли:

a=Car
b=Truck
c=Car faster than Truck
d=Car faster than all

Tag/Value Delimiter:   =
Argument Tag: -> a     Argument Value: -> Car                      
Argument Tag: -> b     Argument Value: -> Truck                    
Argument Tag: -> c     Argument Value: -> Car faster than Truck    
Argument Tag: -> d     Argument Value: -> Car faster than all      

Это сработало для меня.

Haunted 08.08.2024 23:16

Другие вопросы по теме