26

is ist possible to tell String.split("(") function that it has to split only by the first found string "("?

Example:

String test = "A*B(A+B)+A*(A+B)";
test.split("(") should result to ["A*B" ,"A+B)+A*(A+B)"]
test.split(")") should result to ["A*B(A+B" ,"+A*(A+B)"]
Max_Salah
  • 2,407
  • 11
  • 39
  • 68

3 Answers3

47

Yes, absolutely:

test.split("\\(", 2);

As the documentation for String.split(String,int) explains:

The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no greater than n, and the array's last entry will contain all input beyond the last matched delimiter.

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • ruakh I tried your answer, when my reges is "\\(", it works fine but when my regex is "(", it throws Exception. can you say why? – Chandra Sekhar Mar 26 '12 at 14:16
  • 3
    @ChandraSekhar: It's because `(` has a special meaning in Java regular expressions. (For example, `(34)+` means "one or more occurrences of `34`", as opposed to `34+` which means "a `3`, followed by one or more occurrences of `4`.) So the backslash is used to "quote" or "escape" it, and indicate "an actual `(` character" rather than using `(` for its special meaning. – ruakh Mar 26 '12 at 14:21
  • `(` has a special meaning in _any_ regular expressions interpreter (maybe not in some really old or limited ones [?] - not sure - but any I would be likely to use) – Code Jockey Mar 26 '12 at 20:59
  • @CodeJockey: In POSIX Basic Regular Expressions (used in `grep`, `sed`, etc.), `(` means a literal parenthesis, while `\(` introduces a capture group. But Perl regexes, which Java uses a variant of, have been *so* pervasive and influential, that I don't blame you for forgetting that not all regex engines behave the same way. :-) – ruakh Mar 26 '12 at 21:02
  • @ruakh Indeed - in my mind, that fell under the "limited ones" category, though I am far from familiar with every intricacy of POSIX expressions and the differences between ERE and BRE, etc... I know that they have different rules than many of the most popular flavors, and I plan to tread with caution if I am ever FORCED to use them :-D. If I'm not mistaken, POSIX is just a little more "regular" than most "regex" engines and takes a different approach to the utility of text pattern matching. – Code Jockey Mar 26 '12 at 21:18
  • It's also good to mention that second token will always present in result array: `assert "param=".split("=").length == 1;` but `assert "param=".split("=", 2).length == 2;` and second token is empty string `assert "param=".split("=", 2)[1].equals("");` ` – Sergey Ponomarev Aug 18 '15 at 08:01
  • @stokito: It's not true that "second token will always present in result array"; note that, for example, `assert "param".split("=", 2).length == 1;`. It's just that `split` without a numeric argument, or with `0` as the numeric argument, discards trailing empty strings. – ruakh Aug 18 '15 at 15:25
4
test.split("\\(",2);

See javadoc for more info

EDIT: Escaped bracket, as per @Pedro's comment below.

KingCronus
  • 4,509
  • 1
  • 24
  • 49
2

Try with this solution, it's generic, faster and simpler than using a regular expression:

public static String[] splitOnFirst(String str, char c) {
    int idx = str.indexOf(c);
    String head = str.substring(0, idx);
    String tail = str.substring(idx + 1);
    return new String[] { head, tail} ;
}

Test it like this:

String test = "A*B(A+B)+A*(A+B)";
System.out.println(Arrays.toString(splitOnFirst(test, '(')));
System.out.println(Arrays.toString(splitOnFirst(test, ')')));
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 2
    "Simpler"? To each his own, I guess. I find the regex to be the simplest, and plenty fast. Also, it supports strings, and it won't blow up if `str.indexOf(c) == -1`. – ruakh Mar 26 '12 at 14:50
  • 1
    It's simpler because you don't have to know about regular expressions to use it. Sure, it needs a bit of error checking, but that's beyond the question. And if Strings are needed, simply changing the parameter `char c` to `String c` will do the trick. And yes, it's faster, your solution needs to compile and match a regular expression each time it's invoked, and OP will need to escape special characters, which he's unaware of. – Óscar López Mar 26 '12 at 15:05
  • Re: "And yes, it's faster": Well, obviously. I didn't say that the regex is faster, only that it's plenty fast, and much simpler. Re: "simply changing the parameter `char c` to `String c` will do the trick": You'd also have to change `1` to `c.length()`. – ruakh Mar 26 '12 at 15:11
  • 1
    To each his own describes it pretty well -- using regex in many cases also allows dynamic maintenance or adjustment of an algorithm, since the entire "algorithm" can often be contained inside a string (which can be a field in a database or a single value in a properties file). To me, "Split on open parenthesis for a maximum array size of 2" is far more simply represented as `test.split("\\(", 2);` (see? I did it just then) than by the function in your example. Also, compiling the regex can further increase efficiency of it if it is to be used often (not that said expression is very complex). – Code Jockey Mar 26 '12 at 21:11