Регулярное выражение разделения Java

#java #regex #split

#java #регулярное выражение #разделение

Вопрос:

Как я могу разделить строку следующим образом

 "-3.0*6.7 (5/2)*-0.8--12.98 4^-0.5"
  

используя регулярное выражение для

 -3.0,*,6.7, ,(,5,/,2,),*,-0.8,-,-12.98, ,4,^,-0.5
  

Комментарии:

1. @KennyTM 4,-,3 но если бы это было «4—3», то 4,-,-3

Ответ №1:

Использовать regex для этой задачи непрактично: вам лучше создать какой-нибудь токенизатор / лексер для создания токенов из вашего источника ввода. Особенно это затрудняет разделение регулярных выражений из-за унарных знаков минус.

Но чтобы ответить на ваш вопрос, вы могли бы разделить по следующему шаблону:

 (?=[ */()^])|(?<=[ */()^])|(?<=d-)|(?<=d)(?=-)
  

что означает:

                 # Split on:
(?=[ */()^])    #   the empty space that has one of:  , *, /, (, ), ^ ahead of it
|               #   OR
(?<=[ */()^])   #   the empty space that has one of:  , *, /, (, ), ^ before it 
|               #   OR
(?<=d-)        #   the empty space that has a digit followed by a minus sign before it
|               #   OR
(?<=d)(?=-)    #   the empty space that has a digit before it and a minus sign ahead of it
  

Ответ №2:

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

 public class CompactSolver {
  private String input;

  public CompactSolver(String input_) {
   input = input_.trim();
  }

  private char peek(int offset) {
   return offset >= input.length() ? '' :
     input.charAt(offset);
  }

  private boolean consumeIf(char c) {
   if (peek(0) != c)
     return false;
   consume(1);
   return true;
  }

  private String consume(int numChars) {
   if (numChars == 0)
     throw new RuntimeException("syntax error");
   String result = input.substring(0, numChars);
   input = input.substring(numChars).trim();
   return resu<
  }

  public double eval() {
   double lhs = mul();
   if (consumeIf(' '))
     return lhs   eval();
   else if (consumeIf('-'))
     return lhs - eval();
   return lhs;
  }

  private double mul() {
   double lhs = unary();
   if (consumeIf('*'))
     return lhs * mul();
   else if (consumeIf('/'))
     return lhs / mul();
   return lhs;
  }

  private double unary() {
   if (consumeIf('-'))
     return -unary();

   if (consumeIf('(')) {
     double result = eval();
     if (!consumeIf(')'))
       throw new RuntimeException("Missing ')'");
     return resu<
   }

   return literal();
  }

  private double literal() {
   for (int i = 0; true;   i)
     if (!Character.isDigit(peek(i)))
       return Integer.parseInt(consume(i));
  }
}