【问题标题】:How to use line break argument [duplicate]如何使用换行参数[重复]
【发布时间】:2019-03-02 04:49:54
【问题描述】:

我编写了最简单的 Hello, World! 应用程序:

public class Helloworld {

    public static void main(String[] args) {
        System.out.println("Hello\nHello");
    }
}

运行时,结果为:

Hello
Hello

但如果我使用Hello\nHello 作为参数,

public class Helloworld {

    public static void main(String[] args) {
        System.out.println(args[0]);
    }
}

结果是Hello\nHello。如何得到两行结果?

【问题讨论】:

  • @BrankVictoria 我不认为这是这里的问题 - 问题是命令行参数如何到达 java
  • @Hulk 你说得对,我想念这个问题。控制台确实有可能格式化字符串。我的意思是,如果您输入“Hello\nHello”,args[0] 包含的内容将是“Hello\\nHello”
  • 你知道,现在我很好奇......我从来不需要那样的东西......通常,当我需要新行作为参数时,我会使用包含我需要的所有属性的文件输入...... .
  • 如果您使用的是 Linux 或 MacOS,或者任何系统上的 Bash shell,那么您可以使用 java Helloworld 'line one<Enter>line two' 其中<Enter> 表示您按下 Enter 键,这样两行就会出现在不同的行上.单引号将它们保留为单个参数。
  • @DodgyCodeException 正确,你是唯一真正理解这个问题的人!一旦它已经完成,所有的答案都试图修复伤害。问题更多是关于将换行符作为参数传递给您的程序,而不是关于特定程序或 Java。

标签: java


【解决方案1】:

编辑:此答案适用于理解为

的原始问题

为什么当我用 Java 写 Hello\nHello 然后打印它时,我得到两行文本,但是当我在终端中写 Hello\nHello 并将它作为参数传递给我的 Java 程序时,我得到一行文本?

如果你的意思是

有没有办法将一个字符串参数传递给我的 java 程序,该程序打印在多行上?

参见@DodgyCodeException 的answer,它更适合该公式。


当您在 Java 中将 String 定义为 "Hello\nHello" 时,它不包含 '\' 字符。这是换行符的转义序列:"\n" 只是一个字符。 但是,当您将此字符串用作程序的参数时(因此字符串在外部 定义),"\n" 被解释为两个字符:'\''n'。您必须用换行符替换这两个字符,知道要匹配'\',您必须使用'\' 对其进行转义:

System.out.println(args[0].replace("\\n", "\n"));

出于可移植性的考虑,您还可以使用System.lineSeparator() 作为替换字符串。

【讨论】:

  • 好答案,但请注意,您提出的解决方案意味着用户将永远无法再将两个字符“\n”作为参数传递。
  • 好吧,如果您的参数包含应该被解释为换行符的"\n" 和应该保留为两个字符的"\n",那么您应该找到更好的解决方案。即,使用多个参数,或在 Java 中定义字符串。
  • 此解决方案会将用户输入的Hello\\nHello 替换为Hello\
    Hello,即用户仍然无法转义“魔法反斜杠”。
  • 这是 hacky 并且如果用户需要,由于无法转义换行符而导致问题。是的,亚历克斯,有时用户可能想要字面上有“\n”,而其他时候用户可能想要换行符。一个好的系统(如 Dodgy 的回答所示)将允许两者。
  • 你是对的,我想有多种方式可以解释原始问题。我在 Java 端提供了一个解决方法(没有额外的库),DodgyCodeException 在 shell 端提供了一个。我更新了我的答案以反映这一点。
【解决方案2】:

显然你不能马上做,但是做下面的技巧会让你得到你需要的:

System.out.println(String.format(args[0]));

这里使用String#format,并将新行作为新行的转换序列传递。 (见format string syntax)。

所以用

调用你的程序
java Helloworld "hello%nnworld"

将打印

hello
workd

如果你需要自己输出%n,那么你可以用另一个'%'引用'%',即

java Helloworld "hello%%nnworld"

上面将打印:

hello%nnworld

【讨论】:

  • System.out.printf("%s%n", args[0]); 逐字打印命令行参数(即它将打印“Hello%nworld”)。大概你的意思是System.out.printf(args[0]);
  • 是的,因为它被解释为格式,如果 String.format 遇到格式化序列,它将期望一个参数。实际上,在这种情况下,参数应该作为文件传递,或者让应用程序从标准输入中读取。
  • 我最初想的是和你一样的答案,但是有一个不需要的副作用:如果有人用Hello%sHello或类似的方式调用程序,程序会抛出异常。我认为%n\n 好,但我不同意让用户输入printfString.format 的输入
【解决方案3】:

如果您使用的是类 Unix 操作系统,例如 GNU/Linux 或 MacOS,或任何其他系统上的 Bash shell(例如 Windows 上的 Cygwin),那么只需将您的命令行参数括在单引号中,然后您可以插入任意数量的换行符,它仍将被视为单个参数:

$ java Helloworld 'line one
line two'           <-- this is a single argument with an embedded newline

line one            <-- it prints out the output on separate lines!
line two

这不适用于默认的 Windows 命令处理器 (cmd.exe)。如果是这种情况,您可能需要使用以下技术。

您可以使用 Apache Commons Text 中的 StringEscapeUtils.unescapeJava 方法。然后您将能够传递命令行参数并让它们像源代码中的文字字符串一样准确地解释[*]:

import static org.apache.commons.text.StringEscapeUtils.unescapeJava;

public class Helloworld {

    public static void main(String[] args) {
        System.out.println(unescapeJava(args[0]));
    }

}

[*] 排除 Apache 方法中的任何剩余错误。

【讨论】:

  • 很好的答案,因为它是通用的!如果您现在从上面考虑您的评论(真正的问题是您将字母 ` and n` 作为参数传递并且根本不会有问题,如果您对程序的 shell 调用已经解释了 @987654325 @ 正确),这将是完美的!
  • @mastov 谢谢;完成。
  • @mastov+ 许多shell(至少ksh bash zsh)可以使用“ANSI-C 引用”(美元符号然后是引号),例如java HelloWorld $'line one\nline two',或者如果您需要更精细的控制,例如java HelloWorld "hey nonny $var1"$'\n'"ibble gibble $var2"
  • @dave_thompson_085 谢谢,我知道。但重要的信息是:以某种方式接受换行符确实是 shell 的任务。在造成损害后摆弄 Java 中的字符串主要是治标不治本,并且会使程序的许多用户感到困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
  • 2019-12-19
  • 2012-09-27
  • 1970-01-01
相关资源
最近更新 更多