Regex для разбора параметров командной строки - PullRequest
0 голосов
/ 08 ноября 2018

Я столкнулся с необходимостью разбора строки на пары ключ-значение, где значение может быть необязательным. Стандартные парсеры командной строки бесполезны, потому что все, что я проверял, принимают String[], а не String. Таким образом, я прибег к регулярному выражению и, конечно же, столкнулся со следующим:

Некоторые люди, сталкиваясь с проблемой, думают: «Я знаю, я буду использовать регулярные выражения. "Теперь у них есть две проблемы.

Сначала строка ввода:

"/opt/sensu/embedded/bin/ruby /opt/sensu/embedded/bin/check-graphite-stats.rb " +
"--crit 25 --host 99.99.999.9999:8082 --period -5mins --target 'alias(scale(divideSeries(" +
"summarize(sumSeries(nonNegativeDerivative(transformNull(exclude(" +
"\\\"unknown\\\"), 0))), \\\"30d\\\", \\\"sum\\\", false),summarize(" +
...gigantuous string
\\\"sum\\\", false)), 100), \\\"3pp error rate\\\")' " +
"--unknown-ignore --warn 5"

Далее, мое регулярное выражение:

(--(?<option>.+?)\s+(?<value>.+?(?=--))?)+?

выше почти работает, но не совсем.

Выход:

--crit 25 
--host 99.99.999.9999:8082 
--period -5mins 
--target 'gigantuous string' 
--unknown-ignore 
--warn 

Почему значение --warn не взято?

1 Ответ

0 голосов
/ 08 ноября 2018

Поскольку вы выполняете положительный просмотр следующего -- в конце регулярного выражения ((?=--)), значение последнего параметра в строке не принимается, поскольку за ним не следует --. Принятие конца строки в качестве альтернативы ((?:(?=--)|$)) и последующая фильтрация значений, которые не начинаются с -- (путем замены .+? на .(?:[^-].+?)?), должны вести себя так, как вы хотите:

(--(?<option>.+?)\s+(?<value>.(?:[^-].+?)?(?:(?=--)|$))?)+?

(Однако, как уже упоминали другие, я был бы очень удивлен, что не существует библиотеки разбора аргументов Java, которая бы подходила вашему варианту использования. Даже если это означает написание кода для разделения вашей строки на аргументы самостоятельно, это может быть менее хрупким.)

...