5

I have pattern/matcher lines that transform input Strings like this:

1 3 Hi [2 1 4]

into an Array like this:

[0] => "1"
[1] => "3"
[2] => "Hi"
[3] => "2 1 4"

That's the code:

String input = sc.nextLine();

Pattern p = Pattern.compile("(?<=\\[)[^\\]]+|\\w+");
Matcher m = p.matcher(input);
List<String> cIn = new ArrayList<String>();
while(m.find()) cIn.add(m.group());

Now I realised that sometimes I could get some negative values, inputs like 4 2 -1 2. Since the input is a String, i can't really use any regular expression to get that negative value.

Below in the code, I use

Integer.parseInt(cIn.get(0)); 

to transform that string value into the Integer, that is actually what I need.

Could you figure a way that allows me to keep together the - char and the number char? Then I would just check if there's the - char to transform the number and multiply it by -1. (If there's a better way I'd be glad to hear).

As usual, excuse me for my English.

Ken White
  • 123,280
  • 14
  • 225
  • 444
afontcu
  • 170
  • 2
  • 12
  • 1
    +1, and no need to apologize for your English. It's quite good. :-) – Ken White Nov 17 '12 at 01:01
  • Could you just split on spaces and parse normally? Why use a regex? – Dave Newton Nov 17 '12 at 01:02
  • @DaveNewton He wants to capture sequences in `[]` as a token, even if they include whitespace. (But I'm also fond of the regex-less approach!) – cheeken Nov 17 '12 at 01:03
  • @cheeken I meant after the group is captured. Personally this looks more like a job for an actual parser than regex, although if this is as complex as things get, maybe it doesn't matter. – Dave Newton Nov 17 '12 at 01:11
  • It's hard to answer this question - you should really provide a plain description of the full effect of what you're trying to match with this regular expression, as well as perhaps some edge cases which should not match. – FrankieTheKneeMan Nov 17 '12 at 01:12
  • @DaveNewton could be, but I'm just learning Java and I never had to use regex before, so I wanted to give it a try. Performance here isn't really important. Thanks! :) – afontcu Nov 17 '12 at 01:20
  • @afontcu It's not just a matter of performance, it's a matter of suitability and maintainability. Like I said, if it's never more complicated than this, it's probably fine. – Dave Newton Nov 17 '12 at 01:28

4 Answers4

3

You absolutely can use a regular expression to capture negative numbers, but it depends on what you're trying to weed out.

"(?<=\\[)[^\\]]+|[-\\w]+"

The simplest way is to simply add '-' to the group of recognized word characters. However, this will also result in weird formations like '9-9' being legal. Considering you already match tokens like '9_9', I'm not sure that's a problem for you. I'd probably just add another alternation to the end of this regex:

"(?<=\\[)[^\\]]+|\\w+|-?\\d+"

Which allows an optional '-' character followed by at least one digit. Or, a negative number. This is fairly robust - you're literally just defining an additional type of match (a very specific one), but every time you find a new case, you really shouldn't just keep adding '|...' to the end of your regex. It's about the least efficient way to do what you're doing. It seems, in your situation, that this isn't really a problem, but you should think about this as your use case expands.

FrankieTheKneeMan
  • 6,645
  • 2
  • 26
  • 37
  • Hm, thats easier than i thought. I tried to go around and include the "-" char after \\w+ (\\w+\\-) but that didn't work well. I just thought that, since I'm getting a String, I could not evaluate the number as positive or negative. I think I just have to give it more tries before asking on the internet, lesson learned. Thank you all very much. – afontcu Nov 17 '12 at 01:12
3

Here is the way: (?<=\\[)[^\\]]+|-?\\w+.

The -? regex means that you can have a - or not before the word (\\w+) but if you need only digits then use \\d+ and \\w+.

Here is the test i wrote:

@Test
public void regex() {

    String input = "-1 3 Hi [2 1 4]";

    Pattern p = Pattern.compile("(?<=\\[)[^\\]]+|-?\\w+");
    Matcher m = p.matcher(input);
    List<String> cIn = new ArrayList<String>();
    while (m.find())
        cIn.add(m.group());

    System.out.println(cIn);

}

It yields [-1, 3, Hi, 2 1 4] as you expect.

ElderMael
  • 7,000
  • 5
  • 34
  • 53
1

You could use an optional - in your regex:

Pattern p = Pattern.compile("(?<=\\[)[^\\]]+|-?\\w+");
Reimeus
  • 158,255
  • 15
  • 216
  • 276
0

Very fancy regular expression, but what about something with fewer tricks that captures what you are trying to do?

(?:\[(?:\s*[-]?\d+\s*)*\]|(?:[-]?\d+|\w+))
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263