How to split string on '~|~' separator in Java?

Viewed 325

I have input String '~|~' as the delimiter.

For example: String s = "1~|~Vijay~|~25~|~Pune"; when I am splitting it with '~\\|~' in Java it is working fine.

String sa[] = s.split("~\\|~", -1);
for(String str : sa) {
    System.out.println(str);
}

I am getting the below output.

1
Vijay
25
Pune

When the same program I am running by passing a command-line argument('~\\|~'). It is not properly parsing the string and giving it below output.

1
|
Vijay
|
25
|
Pune

Is anyone else facing the same issue? please comment on this issue.

3 Answers

You only need a single backslash when running it from the command line. The reason you need two when making the regular expression in Java is that backslash is used to escape the next character in a string literal or start an escape sequence so one backslash is needed to escape the next one in order for it to be interpreted literally.

~\|~

Please, do a System.out.println("[" + args[i] + "]"); to see what java is receiving from the command line, as the \ character is special for the shell and aso are the | and ~ chars (the last one expands to your home directory, which could be a problem)

You need to pass:

java foo_bar '~\|~'

(Java still needs a single \ this time to escape the vertical bar, as you are not writing a string literal for the java compiler but a simple string representing the internal representation of the above string literal, the \ character doesn't need to be escaped, as it is inside single quotes so it is passed directly to the java program) Any quoting (single or double quotes) suffices to avoid ~ expansion.

If you are passing

java foo_bar '~\\|~'

the shell will not assume the \ as a escaping character and will pass the equivalent to this String literal:

String sa[] = s.split("~\\\\|~", -1); /* to escapes mean a literal escape */

(see that now the vertical bar doesn't have its special significance)

...which is far different (you meant this time: split on one ~\ sequence, this is, a ~ followed by a backslash, or just a single ~ character, and as there are no ~s followed by a backslash, the second option was used. You should get:

1
|
Vijay
|
25
|
Pune

Which is the output you post.

You don't have to escape:

public static void main(String[] args) {
    Pattern p = Pattern.compile(args[0], Pattern.LITERAL);
    final String[] result = p.split("1~|~Vijay~|~25~|~Pune");
    Arrays.stream(result).forEach(System.out::println);
}

Running:

javac Main.java
java Main "~|~"

Output:

1
Vijay
25
Pune

Where args[0] is equal to ~|~ (no escaping). The trick is that pattern flag, Pattern.LITERAL, which treats every character, including |, as normal character, ignoring their meta meaning.

Related