Passing a space-separated System Property via a sh

2019-08-02 14:11发布

问题:

I'm having difficulties to startup a java program from a shell script (bash) where nested variables are used. Basically there are many system and -D java properties that need to be passed to a java program. I would like to organise them in a nicer way one below another as they are very difficult to read when in one line.

This is similar to "Passing a space-separated System Property via a shell script doesn't work" but not the same.

Here is a stripped down sample. Imagine a java program like this:

public class Main {
    public static void main(String[] args) {
        for (String s : args) {
            System.out.println(s);
        }
    }
}

When invoking it like this:

java Main "First_Line" "Second line with spaces"

It will give OK result like this response:

First_Line
Second line with spaces

However if script like this is used:

#!/bin/sh
PARAM01="FirstLine"
PARAM02="Second line with spaces"
PARAMS="$PARAM01 $PARAM02"
java Main $PARAMS

Then all spaces are eaten and second parameter is passed unquoted to java. Result looks like this:

FirstLine
Second
line
with
spaces

Have tried to differently quote variables in a shell script, but so far without success. How to quote shell variables so that spaces are preserved and parameter is passed intact to java?

回答1:

If you put a shell variable on the command line unquoted, then it undergoes word splitting. To prevent that word splitting, keep each parameter in double-quotes:

java Main "$PARAM01" "$PARAM02"

Or, if you want to get fancy, use an array:

PARAMS=("$PARAM01" "$PARAM02")
java Main "${PARAMS[@]}"


回答2:

Or you can't put params into separate file name for instance params.in and using Java8 is easy to work with

public static void main(final String[] args) throws IOException {

    // Loading file (change with your way)
    final Path file = Paths.get("src/main/resources/params.in");

    // Printing lines or working with params
    Files.lines(file).forEach(line -> {System.out.println(line);});
}

Edit: Small mistake, in case params.in is inside src/main/resources then it could be simplified.