【问题标题】:Splitting a command line in Java在 Java 中拆分命令行
【发布时间】:2013-05-19 07:18:49
【问题描述】:

在 Java 中解析类似 shell 的命令行的推荐方法是什么。通过我并不意味着在已经以数组表单(例如处理“-X”)时处理选项,已经有大量的问题和答案。

不,我的意思是将完整的命令字符串拆分为“令牌”。我需要转换一个字符串,例如:

user 123712378 suspend "They are \"bad guys\"" Or\ are\ they?

...到列表/数组:

user
123712378
suspend
They are "bad guys"
Or are they?

我目前只是对空格进行拆分,但这显然无法处理引号和转义空格。

(报价处理是最重要的。转义空格会很好)

注意:我的命令字符串是来自类似 shell 的 Web 界面的输入。它不是从main(String[] args) 构建的

【问题讨论】:

  • 大多数命令行库不是都解决了这个问题吗?你可以看看他们的来源。
  • @tieTYT 据我所知,这些库仅在它们被 shell 分隔后才处理参数。它们用于构建命令,而不是 shell。
  • 您将如何拆分以下内容?:This is"an example"。 IE。您将如何处理前面有非空白字符的左引号?
  • @Lonenebula "This","is","an example"
  • 假设您想要与 shell 使用相同的规则,this is"an example" 将解析为 thisisan example

标签: java parsing command-line-interface


【解决方案1】:

您需要实现一个有限自动机。您需要逐个字符地读取字符串,并根据您的下一个或上一个字符找到下一个状态。
例如," 表示字符串的开始,但如果它前面有 \,则保持当前状态不变并读取直到下一个标记带您进入下一个状态。
IE。基本上在你的例子中你会有

read string -> read number   
      ^  -    -   -  |  

您当然需要定义所有状态以及影响或不影响您的状态的特殊字符。
老实说,我不确定您为什么要向最终用户提供此类功能。
传统上,所有 cli 程序都接受标准格式 -x or --x or --x=s 等的输入。
这种格式为典型用户所熟知,并且易于实施和测试为正确。
传统上,如果我们需要为用户提供更“灵活”的输入,最好构建一个 GUI。这就是我的建议。

【讨论】:

  • 嗯,这很容易构建(我过去也有,用于其他情况),但我希望一些库已经修复了它。关于原因,我不只是自己构建命令(这就是 -x 等进来的地方,他们可能会在我的应用程序中做),但我首先构建 shell 本身,高级用户通过以下方式输入命令字符串一个网络界面。
  • 也许有一个库可以满足您的需求,但我不知道有什么建议。但是如果您要构建这样的外壳并且按照您所说的那样构建实现起来很容易,我建议构建它,而不是依赖另一个库,因为您将构建它以根据需要添加东西(更多/更少的功能、调试等)
【解决方案2】:

来自 DrJava 的ArgumentTokenizer 以 Bourne shell 及其衍生工具的方式解析命令行

它正确支持转义,因此bash -c 'echo "\"escaped '\''single'\'' quote\""' 被标记为[bash, -c, echo "\"escaped 'single' quote\""]

【讨论】:

    【解决方案3】:

    将 args[] 重新构建为字符串,然后使用正则表达式进行标记:

    public static void main(String[] args) {
        String commandline = "";
        for(String arg : args) {
            commandline += arg;
            commandline += " ";
        }
        System.out.println(commandline);
    
        List<String> list = new ArrayList<String>();
        Matcher m = Pattern.compile("([^\"]\\S*|\".+?\")\\s*").matcher(commandline);
        while (m.find())
            list.add(m.group(1)); // Add .replace("\"", "") to remove surrounding quotes.
    
    
        System.out.println(list);
    }
    

    后半部分我取自here

    【讨论】:

      猜你喜欢
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-06
      • 1970-01-01
      • 2010-11-23
      • 2013-02-04
      • 2012-06-05
      相关资源
      最近更新 更多