Шаблон регулярного выражения для сопоставления положительных и отрицательных числовых значений в строке

У меня есть строки шаблона/сопоставителя, которые преобразуют входные строки следующим образом:

1 3 Hi [2 1 4]

в такой массив:

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

Это код:

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());

Теперь я понял, что иногда я мог получить некоторые отрицательные значения, такие как 4 2 -1 2. Поскольку ввод представляет собой строку, я не могу использовать какое-либо регулярное выражение для получения этого отрицательного значения.

Ниже в коде я использую

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

чтобы преобразовать это строковое значение в целое число, это на самом деле то, что мне нужно.

Не могли бы вы придумать способ, который позволит мне сохранить вместе - char и числовой char? Тогда я бы просто проверил, есть ли символ - для преобразования числа и умножения его на -1. (Если есть лучший способ, я был бы рад услышать).

Как обычно, извините меня за мой английский.


person afontcu    schedule 17.11.2012    source источник
comment
+1, и не нужно извиняться за ваш английский. Это очень хорошо. :-)   -  person Ken White    schedule 17.11.2012
comment
Не могли бы вы просто разбить на пробелы и нормально разобрать? Зачем использовать регулярное выражение?   -  person Dave Newton    schedule 17.11.2012
comment
@DaveNewton Он хочет захватить последовательности в [] в качестве токена, даже если они содержат пробелы. (Но мне также нравится подход без регулярных выражений!)   -  person cheeken    schedule 17.11.2012
comment
@cheeken Я имел в виду после захвата группы. Лично это больше похоже на работу для настоящего синтаксического анализатора, чем на регулярное выражение, хотя, если это настолько сложно, насколько это возможно, возможно, это не имеет значения.   -  person Dave Newton    schedule 17.11.2012
comment
Трудно ответить на этот вопрос — вы действительно должны предоставить простое описание полного эффекта того, что вы пытаетесь сопоставить с этим регулярным выражением, а также, возможно, некоторые крайние случаи, которые не должны совпадать.   -  person FrankieTheKneeMan    schedule 17.11.2012
comment
@DaveNewton может быть, но я только изучаю Java, и мне никогда раньше не приходилось использовать регулярное выражение, поэтому я хотел попробовать. Производительность здесь не очень важна. Спасибо! :)   -  person afontcu    schedule 17.11.2012
comment
@afontcu Дело не только в производительности, но и в пригодности и ремонтопригодности. Как я уже сказал, если это никогда не будет сложнее, чем это, то, наверное, все в порядке.   -  person Dave Newton    schedule 17.11.2012


Ответы (4)


Вы абсолютно можете использовать регулярное выражение для захвата отрицательных чисел, но это зависит от того, что вы пытаетесь отсеять.

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

Самый простой способ — просто добавить «-» к группе распознаваемых символов слова. Однако это также приведет к тому, что странные построения, такие как «9-9», будут разрешены. Учитывая, что вы уже сопоставили такие токены, как «9_9», я не уверен, что это проблема для вас. Я бы, наверное, просто добавил еще одно чередование в конец этого регулярного выражения:

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

Что позволяет использовать необязательный символ «-», за которым следует хотя бы одна цифра. Или отрицательное число. Это довольно надежно — вы буквально просто определяете дополнительный тип соответствия (очень специфический), но каждый раз, когда вы находите новый случай, вы действительно не должны просто добавлять «|...» в конец ваше регулярное выражение. Это наименее эффективный способ делать то, что вы делаете. В вашей ситуации кажется, что это на самом деле не проблема, но вам следует подумать об этом по мере расширения вашего варианта использования.

person FrankieTheKneeMan    schedule 17.11.2012
comment
Хм, это проще, чем я думал. Я попытался обойти и включить - char после \\w+ (\\w+\\-), но это не сработало. Я просто подумал, что, поскольку я получаю строку, я не могу оценить число как положительное или отрицательное. Я думаю, что мне просто нужно сделать больше попыток, прежде чем спрашивать в Интернете, урок усвоен. Всем большое спасибо. - person afontcu; 17.11.2012

Вот так: (?<=\\[)[^\\]]+|-?\\w+.

Регулярное выражение -? означает, что у вас может быть - или нет перед словом (\\w+), но если вам нужны только цифры, используйте \\d+ и \\w+.

Вот тест, который я написал:

@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);

}

Это дает [-1, 3, Hi, 2 1 4], как вы ожидаете.

person ElderMael    schedule 17.11.2012

Вы можете использовать необязательный - в своем регулярном выражении:

Pattern p = Pattern.compile("(?<=\\[)[^\\]]+|-?\\w+");
person Reimeus    schedule 17.11.2012

Очень причудливое регулярное выражение, но как насчет чего-то с меньшим количеством приемов, которое фиксирует то, что вы пытаетесь сделать?

(?:\[(?:\s*[-]?\d+\s*)*\]|(?:[-]?\d+|\w+))
person Maarten Bodewes    schedule 17.11.2012