HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Splitting a command line into key/value pairs

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
lineintosplittingvaluecommandpairskey

Problem

The code below will split environment variables from a command line (always appear at the end of the command line). Environment variables are represented by '-E key=value'. I've achieved this like so, but I'm wondering if there's a more elegant way

public class TestSplit {

  public static void main(String... args) {
    String command = "-ps 4 -pe 5 -E opInstallDir=/home/paul -E opWD=/home/paul/remake -E opFam=fam -E opAppli=appli";

    int startPosition = command.indexOf("-E") + 2;

    String envVars = command.substring(startPosition);

    for(String pair: envVars.split("-E")) {
      String[] kv = pair.split("=");
      System.out.println(kv[0] + " " +kv[1]);
    }
  }

}


EDIT Just to clarify these aren't command line arguments for launching the program from the console, they are command line arguments for launching an external program. The details of which I haven't included.

Solution

Like @palacsint I will recommend an external library. Apache commons-cli is a decent choice. Another choice (my preference) is java gnu-getopt ... I like it because I am familiar with the notations and standards from previous work. It can be a little complicated the first time around otherwise.

On the other hand, I tend not to use an external library unless the code is already going to be relatively complicated....

But, back to your code.

Why do you have everything in a single String? Why is it not part of the String...args ?

The first thing about command-line arguments is that they get complicated very fast. What if the argument was:

String command = "-ps 4 -pe 5 -E opInstallDir=/opt/OSS-EVAL/thiscode -E opWD=/home/paul/remake -E opFam=fam -E opAppli=appli -Edocs='My Documents' -Eparse=key=value";


I have thrown in a few things there.

First up, on our one machine at work, we really do have the directory /opt/OSS-EVAL/ which we use to install/evaluate OSS software/libraries.

The above will break your parsing because it has the -E embedded in the name.

Next up, is 'POSIX-style' commandline arguments can have quoted values, and also values with an = in the value.

So, things I would recommend to you:

Locate the source of your command-line values. It will likely be available as an array, not a single string. Keep the data as an array!

Second, with the array, it is easier to look for stand-alone values that are -E, or, if the input is -Ekey=value then you look for values that start with -E.

Finally, when you split the key/value on the =, limit the split to 2.

String[] kv = pair.split("=", 2);


Which will preserve any of the = tokens inside the value part.

EDIT:

You have suggested in your edit that this is for sending data to an external command.

If you are using Java to initialize the external command, then please, please, please use the version of exec() that takes a command array, or use the ProcessBuilder which allows you to send all the command-line parameters as separate values in an array!!!

Code Snippets

String command = "-ps 4 -pe 5 -E opInstallDir=/opt/OSS-EVAL/thiscode -E opWD=/home/paul/remake -E opFam=fam -E opAppli=appli -Edocs='My Documents' -Eparse=key=value";
String[] kv = pair.split("=", 2);

Context

StackExchange Code Review Q#43697, answer score: 4

Revisions (0)

No revisions yet.