参数中的空格和其他特殊字符

首先,在参数中处理空格的问题实际上并不是 Java 问题。相反,它是一个需要由运行 Java 程序时使用的命令 shell 处理的问题。

作为一个例子,让我们假设我们有以下简单的程序来打印文件的大小:

import java.io.File;

public class PrintFileSizes {
    
    public static void main(String[] args) {
        for (String name: args) {
            File file = new File(name);
            System.out.println("Size of '" + file + "' is " + file.size());
        }
    }
}

现在假设我们想要打印路径名中包含空格的文件的大小; 例如/home/steve/Test File.txt。如果我们运行这样的命令:

$ java PrintFileSizes /home/steve/Test File.txt

shell 不会知道/home/steve/Test File.txt 实际上是一个路径名。相反,它将向 Java 应用程序传递 2 个不同的参数,这些参数将尝试查找各自的文件大小,并且因为具有这些路径(可能)的文件不存在而失败。

使用 POSIX shell 的解决方案

POSIX 外壳包括 sh 以及 bashksh 等衍生物。如果你正在使用其中一个 shell,那么你可以通过引用参数来解决问题。

$ java PrintFileSizes "/home/steve/Test File.txt"

路径名周围的双引号告诉 shell 它应该作为单个参数传递。发生这种情况时,将删除引号。还有其他几种方法可以做到这一点:

$ java PrintFileSizes '/home/steve/Test File.txt'

单(直)引号被视为双引号,除了它们还抑制参数内的各种扩展。

$ java PrintFileSizes /home/steve/Test\ File.txt

反斜杠会转义以下空格,并使其不被解释为参数分隔符。

为了更全面的文档,包括如何在参数处理其他特殊字符的描述,请参阅引用主题的 Bash文档。

Windows 解决方案

Windows 的基本问题是在操作系统级别,参数作为单个字符串( ) 传递给子进程。这意味着解析(或重新解析)命令行的最终责任落在程序或其运行时库上。有很多不一致的地方。

在 Java 案例中,简要说一下:

  • 你可以在 java 命令中的参数周围放置双引号,这样就可以传递带有空格的参数。

  • 显然,java 命令本身正在解析命令字符串,它或多或少地得到它

  • 但是,当你尝试将此与在批处理文件中使用 SET 和变量替换相结合时,是否会删除双引号会变得非常复杂。

  • cmd.exe 壳显然有其他逃逸机制; 例如,加倍双引号,并使用^转义。

有关更多详细信息,请参阅批处理文件文档。