Как разбить строку и сохранить определенные разделители? - PullRequest
1 голос
/ 05 апреля 2019

Я писал некоторый код, который должен был принимать ввод калькулятора пользователя, поэтому я решил использовать регулярные выражения для токенизации входной строки, но токенизация самой строки не проходит мои модульные тесты на десятичные дроби и "]" .

Я начал с использования метода lookahead и lookbehind, который увидел здесь .

Я написал с "((?<=[+-/*(){^}[%]π])|(?=[+-/*(){^}[%]π]))"; который компилировался и работал успешно, за исключением того, что это не удалось, если было число с десятичной дробью.

Я вернулся и попробовал его так же, как принятый ответ в связанном вопросе, используя "[+-/*\\^%(){}[]]" (regex3 ниже) как с π, так и без него, потому что моим первым инстинктом был бы персонаж, вызвавший проблему, но в в обоих случаях это привело к Exception in thread "main" java.util.regex.PatternSyntaxException: Unclosed character class near index 41 ((?<=[+-/*\^%(){}[]])|(?=[+-/*\^%(){}[]]))

В этот момент я вернулся к своей первой попытке и переставил термины, "((?<=[+-/*^%(){}[]π])|(?=[+-/*^%(){}[]π]))"; (regex2 ниже), но у этого также было то же PatternSyntaxException в последней скобке.

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

import java.util.Arrays;
public class RegexProblem {
    /** This Delimiter string came from {@link https://stackoverflow.com/a/2206432/} */
    static public final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))";


    // Split on and include + - * / ^ % ( ) [ ] { } π
    public static void main(String[] args) {

        String regex1="((?<=[+-/*(){^}[%]π])|(?=[+-/*(){^}[%]π]))";
        String regex2="((?<=[+-/*^%(){}[]π])|(?=[+-/*^%(){}[]π]))";
        String regex3="[+-/*\\^%(){}[]]";

        String str="1.2+3-4^5*6/(78%9π)+[{0+-1}*2]";
        String str2="[1.2+3]*4";


        String[] expected={"1.2","+","3","-","4","^","5","*","6","(","78","%",
                           "9","π",")","+","[","{","0","+","-","1","}","*","2","]"};
        String[] expected2={"[","1.2","+","3","]","*","4"};


        System.out.println("Expected: ");
        System.out.print("str: ");
        System.out.println(Arrays.toString(expected));
        System.out.print("str2: ");
        System.out.println(Arrays.toString(expected2));
        System.out.println();


        System.out.println();
        System.out.println("Regex1: ");
        System.out.print("str: ");
        System.out.println(Arrays.toString(str.split(regex1)));
        System.out.print("str2: ");
        System.out.println(Arrays.toString(str2.split(regex1)));
        System.out.println();
        System.out.println("Regex2: ");
        System.out.print("str: ");
        System.out.println(Arrays.toString(str.split(regex2)));
        System.out.print("str2: ");
        System.out.println(Arrays.toString(str2.split(regex2)));
        System.out.println();
        System.out.println("Regex3: ");
        System.out.print("str: ");
        System.out.print(Arrays.toString(str.split(String.format(WITH_DELIMITER, regex3))));
        System.out.print("str2: ");
        System.out.print(Arrays.toString(str2.split(String.format(WITH_DELIMITER, regex3))));

    }

}

Запуск regex2 и regex 3 не удался, но меня сбивает с толку поведение regex1, которое запускается, даже если у него такое же количество закрывающих символов, как и у других, и разделяется с помощью «.» но не "]".

1 Ответ

1 голос
/ 06 апреля 2019

Попробуйте:

(?<=[^\d.])|(?=[^\d.])

Объяснение:

  • \d - сокращение от [0-9], поэтому любая цифра.
  • . в квадратных скобках просто соответствует буквальной точке, которая, кажется, всегда является частью числа в вашем примере ввода.Поэтому [\d.] - это то, что мы будем использовать для идентификации числовых символов.
  • [^\d.] соответствует нечисловому символу (карат ^ отрицает класс символов).
  • (?<=[^\d.]) соответствует точке, которой предшествует нечисловой символ.
  • Alternate (?=[^\d.]) соответствует точке, за которой следует нецифровый символ.
...