Как разобрать командную строку с регулярными выражениями? - PullRequest
6 голосов
/ 13 октября 2008

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

"param 1" param2 "param 3"

должно привести к:

парам 1, парам2, парам 3

Ответы [ 13 ]

14 голосов
/ 13 октября 2008

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

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

>>> import shlex
>>> shlex.split('"param 1" param2 "param 3"')
['param 1', 'param2', 'param 3']
>>> shlex.split('"param 1" param2 "param 3')
Traceback (most recent call last):
    [...]
ValueError: No closing quotation
>>> shlex.split('"param 1" param2 "param 3\\""')
['param 1', 'param2', 'param 3"']

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

6 голосов
/ 13 октября 2008

Я склонен использовать regexlib для такого рода проблем. Если вы перейдете по адресу: http://regexlib.com/ и выполните поиск по «командной строке», вы найдете три результата, которые выглядят так, как будто они пытаются решить эту или подобные проблемы - это должно быть хорошим началом.

Это может работать: http://regexlib.com/Search.aspx?k=command+line&c=-1&m=-1&ps=20

5 голосов
/ 13 октября 2008

Без учета языка реализации ваше регулярное выражение может выглядеть примерно так:

("[^"]*"|[^"]+)(\s+|$)

Первая часть "[^"]*" ищет строку в кавычках, которая не содержит встроенных кавычек, а вторая часть [^"]+ ищет последовательность символов без кавычек. \s+ соответствует разделяющей последовательности пробелов, а $ соответствует концу строки.

4 голосов
/ 08 ноября 2013
("[^"]+"|[^\s"]+)

что я использую C ++

#include <iostream>
#include <iterator>
#include <string>
#include <regex>

void foo()
{
    std::string strArg = " \"par   1\"  par2 par3 \"par 4\""; 

    std::regex word_regex( "(\"[^\"]+\"|[^\\s\"]+)" );
    auto words_begin = 
        std::sregex_iterator(strArg.begin(), strArg.end(), word_regex);
    auto words_end = std::sregex_iterator();
    for (std::sregex_iterator i = words_begin; i != words_end; ++i)
    {
        std::smatch match = *i;
        std::string match_str = match.str();
        std::cout << match_str << '\n';
    }
}

Выход:

"par   1"
par2
par3
"par 4"
2 голосов
/ 13 октября 2008

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

Регулярные выражения являются очень мощными инструментами и полезны для широкого спектра задач, но есть также много проблем, для которых они не являются лучшим решением. Это один из них.

1 голос
/ 06 марта 2014

Это отделит exe от его параметров; удаление скобок из exe; предполагает чистые данные:

^(?:"([^"]+(?="))|([^\s]+))["]{0,1} +(.+)$

Вы будете проводить два матча одновременно из трех групп матчей:

  1. Отлично, если он был заключен в скобки
  2. Exe, если он не был заключен в скобки
  3. Скопление параметров

Примеры:

"C:\WINDOWS\system32\cmd.exe" /c echo this

Матч 1: C:\WINDOWS\system32\cmd.exe

Матч 2: $ null

Матч 3: /c echo this

C:\WINDOWS\system32\cmd.exe /c echo this

Матч 1: $ null

Матч 2: C:\WINDOWS\system32\cmd.exe

Матч 3: /c echo this

"C:\Program Files\foo\bar.exe" /run

Матч 1: C:\Program Files\foo\bar.exe

Матч 2: $ null

Матч 3: /run

Мысли:

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

Это регулярное выражение может быть легко зациклено на третьем матче, пока матч не завершится неудачей; больше нет параметров.

0 голосов
/ 07 декабря 2016

Регулярное выражение: /[\/-]?((\w+)(?:[=:]("[^"]+"|[^\s"]+))?)(?:\s+|$)/g

Образец: /P1="Long value" /P2=3 /P3=short PwithoutSwitch1=any PwithoutSwitch2

Такое регулярное выражение может анализировать список параметров, построенный по правилам:

  • Параметры разделяются пробелами (один или несколько).
  • Параметр может содержать символ переключателя (/ или -).
  • Параметр состоит из имени и значения, разделенных на символ = или :.
  • Имя может содержать буквенно-цифровые символы и подчеркивания.
  • Значение может отсутствовать.
  • Если значение существует, это может быть набор любых символов, но если оно имеет пробел, значение должно быть заключено в кавычки.

Это регулярное выражение имеет три группы:

  • первая группа содержит целые параметры без символа переключателя,
  • вторая группа содержит только имя,
  • третья группа содержит только значение (если оно существует).

Для примера выше:

  1. Всего совпадений: /P1="Long value"
    • Группа № 1: P1="Long value",
    • Группа № 2: P1,
    • Группа № 3: "Long value".
  2. Всего совпадений: /P2=3
    • Группа № 1: P2=3,
    • Группа № 2: P2,
    • Группа № 3: 3.
  3. Всего совпадений: /P3=short
    • Группа № 1: P3=short,
    • Группа № 2: P3,
    • Группа № 3: short.
  4. Всего совпадений: PwithoutSwitch1=any
    • Группа № 1: PwithoutSwitch1=any,
    • Группа № 2: PwithoutSwitch1,
    • Группа № 3: any.
  5. Всего совпадений: PwithoutSwitch2
    • Группа № 1: PwithoutSwitch2,
    • Группа № 2: PwithoutSwitch2,
    • Группа № 3: отсутствует.
0 голосов
/ 25 июля 2012
\s*("[^"]+"|[^\s"]+)

Вот и все

0 голосов
/ 11 мая 2012

есть ответ на языке python, поэтому мы также получим ответ ruby:)

require 'shellwords'
Shellwords.shellsplit '"param 1" param2 "param 3"'
#=> ["param 1", "param2", "param 3"] or :
'"param 1" param2 "param 3"'.shellsplit
0 голосов
/ 17 декабря 2011

Если вы хотите проанализировать команду и параметры, я использую следующее (с ^ $ соответствием в разрывах строк, или многострочном):

(?<cmd>^"[^"]*"|\S*) *(?<prm>.*)?

Если вы хотите использовать его в своем коде C #, здесь он правильно экранирован:

try {
    Regex RegexObj = new Regex("(?<cmd>^\\\"[^\\\"]*\\\"|\\S*) *(?<prm>.*)?");

} catch (ArgumentException ex) {
    // Syntax error in the regular expression
}

Он проанализирует следующее и узнает, что это за команда и параметры:

"c:\program files\myapp\app.exe" p1 p2 "p3 with space"
app.exe p1 p2 "p3 with space"
app.exe
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...