15

I wrote the most simple Hello, World! application:

public class Helloworld {

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

When it runs, the result is:

Hello
Hello

But if I use Hello\nHello as arguments,

public class Helloworld {

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

the result is Hello\nHello. How do I get the two-line result?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kk luo
  • 549
  • 1
  • 9
  • 22
  • 12
    @BrankVictoria I don't think that is the problem here - the problem is how the command line argument arrives in java – Hulk Sep 26 '18 at 12:01
  • 3
    @Hulk you're right I miss understood the question. It is really possible that the console formats the string. I mean that if you input "Hello\nHello" what does args[0] contains would be "Hello\\nHello" – Brank Victoria Sep 26 '18 at 12:03
  • You know, now I'm curious... I never needed something like that... Usually, when I needed new lines as arguments, I used a file input with all properties I need... – Leonardo Alves Machado Sep 26 '18 at 12:07
  • 2
    If you are using Linux or MacOS, or the Bash shell on any system, then you can use `java Helloworld 'line oneline two'` where `` means you press the Enter key so that the two lines appear on separate lines. The single quotes keep them as a single argument. – DodgyCodeException Sep 26 '18 at 12:17
  • @DodgyCodeException Correct, you are the only one who actually understood the question! All the answers are trying to fix the harm once it's already done. The question is more about passing a newline as argument to your program than it is about the specific program or Java. – mastov Sep 26 '18 at 16:19
  • this question is not a duplicate but it is marked duplicate the link given and the question here are different. – The Scientific Method Oct 05 '18 at 14:25

3 Answers3

16

EDIT: This answer is for the original question understood as

How come when I write Hello\nHello in Java and then print it, I get two lines of text, but when I write Hello\nHello in my terminal and pass it to my Java program as an argument, I get one line of text?

If you mean

Is there a way to pass one string argument to my java program which gets printed on multiple lines?

see @DodgyCodeException's answer, which is better suited to that formulation.


When you define a String as "Hello\nHello" in Java, it contains no '\' character. It is an escape sequence for the line break: "\n" is just one character. When you use this string as an argument to your program, however (so the string is defined outside), "\n" is interpreted as two characters: '\' and 'n'. You have to replace these two characters with the line break, knowing that to match '\' you have to escape it with '\':

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

For portability concerns, you can also use System.lineSeparator() as the replacement string.

Alex M
  • 885
  • 9
  • 12
  • 3
    Good answer, but note that your proposed solution means the user will never again be able to pass the two characters "\n" as an argument. – DodgyCodeException Sep 26 '18 at 12:14
  • 1
    Well, if your arguments contains `"\n"`'s that should be interpreted as line breaks and `"\n"`'s that should remain as two characters, then you should find a better solution. Namely, using more than one argument, or defining the string in Java. – Alex M Sep 26 '18 at 12:26
  • 2
    This solution will replace user input `Hello\\nHello` with ``Hello\``
    `Hello`, i.e. the user is still unable to escape the "magic backslash".
    – Ruslan Sep 26 '18 at 16:08
  • 1
    This is hacky and causes problems by not being able to escape the newline character if the user wants. Yes, Alex, sometimes users may want to literally have "\n" and other times the user might want a newline. A good system (as shown in Dodgy's answer) will permit both. – Greg Schmit Sep 26 '18 at 19:46
  • You are correct, and I guess there are multiple ways the original question can be interpreted. I gave a workaround on the Java side (without additional libraries), and DodgyCodeException gave one on the shell side. I updated my answer to reflect that. – Alex M Sep 27 '18 at 08:34
9

If you are using a Unix-like OS such as GNU/Linux or MacOS, or a Bash shell on any other system (such as Cygwin on Windows), then just enclose your command-line argument in single quotes, and you can insert any number of newlines and it will still be treated as a single argument:

$ 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

This will not work on the default Windows Command Processor (cmd.exe). If that case, you might want to use the following technique.

You could use the StringEscapeUtils.unescapeJava method from Apache Commons Text. Then you will be able to pass command-line arguments and have them interpreted exactly[*] like a literal string in source code:

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

public class Helloworld {

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

}

[*] Barring any remaining bugs in the Apache method.

DodgyCodeException
  • 5,963
  • 3
  • 21
  • 42
  • Good answer because it's universal! If you now factor in your comment from above (that the real problem is that you are passing the letters `\` and `n` as arguments and wouldn't have the problem at all, if your shell call to the program already interpreted the `\n` correctly), it would be perfect! – mastov Sep 26 '18 at 16:23
  • @mastov thanks; done. – DodgyCodeException Sep 26 '18 at 16:33
  • 1
    @mastov+ which many shells (at least `ksh bash zsh`) can do with "ANSI-C quoting" (dollarsign then quotemark) like `java HelloWorld $'line one\nline two'` or if you need finer control something like `java HelloWorld "hey nonny $var1"$'\n'"ibble gibble $var2"` – dave_thompson_085 Sep 26 '18 at 18:15
  • @dave_thompson_085 Thank you, I know. But the important message is: It's really the shell's task to accept the newlines in some way. Fiddling around with the Strings in Java after the harm is done is mostly curing the symptoms and will confuse many users of your program. – mastov Sep 27 '18 at 09:19
6

Apparently you can't do it straight away but doing the following trick will get you what you need:

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

Here String#format is used and the new line is passed as the conversion sequence for a new line. (see the format string syntax).

So call your program with

java Helloworld "hello%nnworld"

will print

hello
workd

and if you need to output %n itself then you can quote '%' with another '%' i.e.

java Helloworld "hello%%nnworld"

The above will print:

hello%nnworld
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
A4L
  • 17,353
  • 6
  • 49
  • 70
  • 1
    `System.out.printf("%s%n", args[0]);` prints the command-line argument verbatim (i.e. it will print "Hello%nworld"). Presumably you meant `System.out.printf(args[0]);`. – DodgyCodeException Sep 26 '18 at 12:33
  • yes, because it is interpreted as format and String.format will expect an argument if it encounters an formatting sequence. Actually in this case arguments should passed as file or making the app read from stdin. – A4L Sep 26 '18 at 12:34
  • 2
    I was first thinking about the same answer as you, but there is an unwanted side effect: if someone calls the program with `Hello%sHello` or similar, the program will throw an exception. I think `%n` is better than `\n` but I do not agree to let the user to type in the input for `printf` or `String.format` – Honza Zidek Sep 26 '18 at 14:01