Java; Рядок замінити (використовуючи регулярні вирази)?


129

У рамках проекту для школи мені потрібно замінити рядок із форми:

5 * x^3 - 6 * x^1 + 1

до чогось типу:

5x<sup>3</sup> - 6x<sup>1</sup> + 1

Я вважаю, що це можна зробити за допомогою регулярних виразів, але я ще не знаю, як це зробити.

Ви можете мені подати руку?

PS Дійсною задачею є реалізація програми Java Polynomial Processing, і я використовую це для передачі polynomial.toString () від моделі до перегляду, і я хочу зробити його досить за допомогою html-тегів.


2
Вибачте, ви можете бути більш конкретним? Я не розумію, що ти маєш на увазі.
Дан Бурцо

5
Старий жарт. codinghorror.com/blog/archives/001016.html має пояснення.
Майкл Майерс

1
О :) Я думаю, що я насправді читав цю статтю назад ... Тож ви припускаєте, що в моєму випадку регулярний вираз не є способом?
Дан Бурцо

Отже, ви дозволяєте тільки поліноми в розгорнутому вигляді?
Адам Яскевич

Відповіді:


176
str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");

ах ... але ви пропустили згортання "5 * x" на "5x"
Джеймс Курран

Пара проблем: \ ^ має бути \\ ^, а $ має бути \ $.
cdmckay

Все ще виникає помилка "недійсна послідовність відходу" ... я щось пропускаю?
Дан Бурцо

це дає мені помилку при другому параметрі: str.replaceAll ("\\ ^ ([0-9] +)", "<sup> \ $ 1 </sup>"); Я не розумію ... :(
Дан Бурцо

2
Чи можливо використовувати попередньо складений шаблон? Це може бути корисно, якщо ви замінюватимете все одним і тим же регулярним виразом багато разів.
qed

38
private String removeScript(String content) {
    Pattern p = Pattern.compile("<script[^>]*>(.*?)</script>",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    return p.matcher(content).replaceAll("");
}

8
Це найкращий IMO, оскільки він використовує компільований Regex, але об'єкт Pattern повинен бути статичним об'єктом.
Марсель Вальдес Ороско

Приємно те, що replaceAllметод неявно робить Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)! Отже, якщо ви повторно використовуєте шаблон таким чином, зайвих об’єктів буде уникнути. Крім того, як говорить @MarcelValdezOrozco, створення його статичним буде запобігати зайвим викликам компіляції шаблонів. :)
varun

20
String input = "hello I'm a java dev" +
"no job experience needed" +
"senior software engineer" +
"java job available for senior software engineer";

String fixedInput = input.replaceAll("(java|job|senior)", "<b>$1</b>");

10
import java.util.regex.PatternSyntaxException;

// (:?\d+) \* x\^(:?\d+)
// 
// Options: ^ and $ match at line breaks
// 
// Match the regular expression below and capture its match into backreference number 1 «(:?\d+)»
//    Match the character “:” literally «:?»
//       Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single digit 0..9 «\d+»
//       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
// Match the character “ ” literally « »
// Match the character “*” literally «\*»
// Match the characters “ x” literally « x»
// Match the character “^” literally «\^»
// Match the regular expression below and capture its match into backreference number 2 «(:?\d+)»
//    Match the character “:” literally «:?»
//       Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single digit 0..9 «\d+»
//       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
try {
    String resultString = subjectString.replaceAll("(?m)(:?\\d+) \\* x\\^(:?\\d+)", "$1x<sup>$2</sup>");
} catch (PatternSyntaxException ex) {
    // Syntax error in the regular expression
} catch (IllegalArgumentException ex) {
    // Syntax error in the replacement text (unescaped $ signs?)
} catch (IndexOutOfBoundsException ex) {
    // Non-existent backreference used the replacement text
}

1
@Dan: Будьте впевнені, що ви розумієте, що робить регекс! Режекси небезпечні для рук людей, які майже їх знають. (Звідси цитата, яку я розмістив.)
Майкл Майєрс

@Dan, як зараз, регулярний вираз очікує пробіл перед і після кожного *. Це можна вирішити в регулярному виразі, але залишимо це як вправу.
Lieven Keersmaekers

@Dan. Я трохи змінив регулярний вираз після створення коментарів. Оригінал був: (:? \ D +) * x \ ^ (:? \ D) Новим є: (:? \ D +) * x \ ^ (:? \ D +)
Lieven Keersmaekers

10
"5 * x^3 - 6 * x^1 + 1".replaceAll("\\W*\\*\\W*","").replaceAll("\\^(\\d+)","<sup>$1</sup>");

Зверніть увагу, що об'єднання обох замін в один регулярний вираз / заміна буде поганим вибором, оскільки більш загальні вирази, такі як x^3 - 6 * xне вдасться.


3

Якщо це стосується будь-якого загального математичного вираження, і дужки в дужках дозволені, це буде дуже важко (можливо, неможливо) зробити це регулярними виразами.

Якщо єдині заміни - це ті, які ви показали, зробити це не так важко. Спочатку *викресліть, а потім використовуйте захоплення, як показав Кан Берк Ґюдер ^.


Так, я пізніше пояснив у примітці PS, що я використовую це для аналізу базового рядкового подання полінома на щось більш читабельне для людини. Дякую!
Дан Бурцо

Поліноми можуть бути розширені до форми, що не містить дужкових виразів. Батьківський збіг - це дуже цікаво, тому не варто обмежуватися лише розширеною формою.
Адам Яскевич

3

Який твій многочлен? Якщо ви "обробляєте" це, я передбачаю, що в якийсь момент генерується якесь дерево суб-виразів, і я думаю, що використовувати його для створення рядка буде набагато простіше, ніж повторно розбирати необроблений вираз з регулярним виразом.

Просто викидаючи інший спосіб мислення там. Я не впевнений, що ще відбувається у вашому додатку.


Я розумію, що ти кажеш ... це справді позбавило б мене від багатьох страждань, але я намагаюся все тримати окремо. Я хотів, щоб Polynomial був окремим класом, який можна використовувати в іншому контексті, наприклад консолі ... але мій підхід може бути неправильним. Що ти думаєш?
Дан Бурцо

Я бачу, що ти маєш на увазі. Включення тегів html у Polynomial.toString () безумовно порушує MVC. Я думаю, що все-таки зробив би щось подібне, бо це дійсно полегшило б справи. Можливо, toHtmlString () чи щось ...
Адам Яскевич

Або, можливо, окремий клас, який View використовує спеціально для форматування полінома? Тоді самому класу Polynomial не потрібно нічого знати про форматування.
Герм

я зробив новий метод: toHTML (); коли ви думаєте про це, toString () і toHTML () - це принципово одне й те саме, за винятком того, що вони використовують різні правила форматування;
Дан Бурцо

Так, мені не дуже подобається, що формат, орієнтований на перегляд, є в об'єкті, але це дозволить вам використовувати поліморфізм для вирішення багатьох логік, а не гігантських операторів перемикання в статичному методі корисності. Коли справа доходить до цього, то toString () також форматування, що залежить від перегляду ...
Адам Яскевич

1

Спробуйте це:

String str = "5 * x^3 - 6 * x^1 + 1";
String replacedStr = str.replaceAll("\\^(\\d+)", "<sup>\$1</sup>");

Обов’язково імпортуйте java.util.regex.


Дякуємо за пораду "імпорт". На жаль, Eclipse видає мені помилку для другого параметра: "Неправильна послідовність втечі"
Dan Burzo

Гмммм ... я тестую його в GroovyConsole, але не на Java. Ви також повинні переконатися, що це все на коробці Java (тобто скласти клас та передати це основним методом).
cdmckay

Рядок заміни повинен бути "<sup> $ 1 </sup>" - не буде зворотних нахилів. Groovy має різні правила щодо відкосів; ви повинні перевірити свій код на Java.
Алан Мур

1
class Replacement 
{
    public static void main(String args[])
    {
        String Main = "5 * x^3 - 6 * x^1 + 1";
        String replaced = Main.replaceAll("(?m)(:?\\d+) \\* x\\^(:?\\d+)", "$1x<sup>$2</sup>");
        System.out.println(replaced);
    }
}

0

Ви хочете розглянути захоплення в регулярному виразі, щоб обробити обгортання 3 в ^ 3.


0

Спробуйте це, можливо, не найкращий спосіб. але це працює

String str = "5 * x^3 - 6 * x^1 + 1";
str = str.replaceAll("(?x)(\\d+)(\\s+?\\*?\\s+?)(\\w+?)(\\^+?)(\\d+?)", "$1$3<sup>$5</sup>");
System.out.println(str);

7
Питання було з 2009 року і на нього вже є 8 відповідей. Перша відповідь має 82 голоси. Ваша відповідь буквально говорить, що "може бути не найкращим способом", вказуючи, що в цій нитці вже є кращі рішення.
Ерік Г

Я не бачу "кращої" відповіді над цим ... Однак є одна, яка в деяких випадках краще нижче.
sergeych

0

Погляньте на antlr4. Це дозволить зробити вас набагато далі в створенні структури дерева, ніж самі регулярні вирази.

https://github.com/antlr/grammars-v4/tree/master/calculator (калькулятор.g4 містить потрібну вам граматику)

Коротше кажучи, ви визначаєте граматику для розбору виразу, використовуєте antlr для генерування коду Java, а також додаєте зворотні виклики для обробки оцінювання під час створення дерева.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.