如何使用正则表达式解析命令行?

时间:2008-10-13 10:48:46

标签: regex parsing

我想在单个字符串参数中拆分像string这样的命令行。如何查看正则表达式。问题是参数可以引用。例如:

“param 1”param2“param 3”

应该导致:

param 1,param2,param 3

13 个答案:

答案 0 :(得分:14)

您不应该使用正则表达式。写一个解析器,或使用你的语言提供的解析器。

我不明白为什么我会为此而投票。这是如何在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"']

现在告诉我,破坏你的大脑关于正则表达式将如何解决这个问题是值得的麻烦。

答案 1 :(得分:6)

我倾向于使用regexlib来解决这类问题。如果你去:http://regexlib.com/并搜索“命令行”,你会发现三个结果,看起来他们正试图解决这个或类似的问题 - 应该是一个好的开始。

这可能有效: http://regexlib.com/Search.aspx?k=command+line&c=-1&m=-1&ps=20

答案 2 :(得分:5)

不考虑实现语言,您的正则表达式可能如下所示:

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

第一部分"[^"]*"查找不包含嵌入引号的带引号的字符串,第二部分[^"]+查找一系列非引号字符。 \s+匹配空格的分隔序列,$匹配字符串的结尾。

答案 3 :(得分:4)

("[^"]+"|[^\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"

答案 4 :(得分:2)

大多数语言都有其他功能(内置或由标准库提供),它比构建自己的正则表达式更容易解析命令行,而且你知道他们会开箱即用。如果您编辑帖子以识别您正在使用的语言,我相信此处的某位人员可以指向您使用该语言的语言。

正则表达式是非常强大的工具,可用于各种各样的事情,但也有许多问题,它们不是最佳解决方案。这是其中之一。

答案 5 :(得分:1)

这将从它的参数中分离出一个exe;从exe中剥离括号;假设干净的数据:

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

您将一次有两个匹配,分为三个匹配组:

  1. 如果它包含在括号中的exe
  2. exe如果没有用括号括起来
  3. 参数丛
  4. <强>示例:

    "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

    <强>思想:

    我很确定你需要创建一个循环来捕获可能无限数量的参数。

    这个正则表达式可以轻松地循环到它的第三场比赛,直到比赛失败;没有更多的参数。

答案 6 :(得分:0)

类似的东西:

"(?:(?<=")([^"]+)"\s*)|\s*([^"\s]+)

或更简单的一个:

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

(仅为了找到正则表达式;))

多次应用,n°1组将为您提供参数,无论是否用双引号括起来。

答案 7 :(得分:0)

如果它只是你担心的引号,那么只需编写一个简单的循环就可以逐个字符地转换为忽略引号的字符串。

或者,如果您使用的是某些字符串操作库,则可以使用它来删除所有引号,然后将它们连接起来。

答案 8 :(得分:0)

如果您要解析命令和参数,我使用以下内容(在换行符处使用^ $匹配,也就是多行):

(?<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

答案 9 :(得分:0)

有一个python答案,因此我们也会得到一个红宝石的答案:)

require 'shellwords'
Shellwords.shellsplit '"param 1" param2 "param 3"'
#=> ["param 1", "param2", "param 3"] or :
'"param 1" param2 "param 3"'.shellsplit

答案 10 :(得分:0)

正则表达式:/[\/-]?((\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组:缺席。

答案 11 :(得分:-1)

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

就是这样

答案 12 :(得分:-3)

(再次阅读你的问题,就在发布之前我注意你说命令行LIKE字符串,因此这些信息可能对你没用,但正如我写的那样我会发帖 - 请忽略我是否误解你的问题。)

如果你澄清你的问题,我会尽力帮助你,但是从你所说的一般性评论中我不会这样做:-),你要求regexp将一系列参数分成一个数组。我强烈建议您考虑使用getopt,而不是自己这样做,这个库的版本适用于大多数编程语言。如果您将来需要,Getopt将按照您的要求进行操作并进行扩展以管理更复杂的参数处理。

如果您让我知道您使用的语言,我会尝试为您发布样本。

以下是主页的示例:

http://www.codeplex.com/getopt     (.NET)

http://www.urbanophile.com/arenn/hacking/download.html     (Java)的

示例(来自上面的java页面)

 Getopt g = new Getopt("testprog", argv, "ab:c::d");
 //
 int c;
 String arg;
 while ((c = g.getopt()) != -1)
   {
     switch(c)
       {
          case 'a':
          case 'd':
            System.out.print("You picked " + (char)c + "\n");
            break;
            //
          case 'b':
          case 'c':
            arg = g.getOptarg();
            System.out.print("You picked " + (char)c + 
                             " with an argument of " +
                             ((arg != null) ? arg : "null") + "\n");
            break;
            //
          case '?':
            break; // getopt() already printed an error
            //
          default:
            System.out.print("getopt() returned " + c + "\n");
       }
   }