Ява; Замена строки (с использованием регулярных выражений)?


129

В рамках школьного проекта мне нужно заменить строку из формы:

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

примерно так:

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

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

Вы можете мне помочь?

PS Фактическое назначение состоит в том, чтобы реализовать Java-приложение для полиномиальной обработки, и я использую его для передачи polynomial.toString () из модели в представление, и я хочу отображать его с помощью тегов html в красивой форме.


2
Простите, а можно подробнее? Я не понимаю о чем ты.
Дэн Бурзо,

5
Старая шутка. codinghorror.com/blog/archives/001016.html есть объяснение.
Майкл Майерс

1
О :) Думаю, я действительно прочитал эту статью некоторое время назад ... Итак, вы предлагаете, чтобы регулярное выражение не подходило в моем случае?
Дэн Бурзо,

Значит, вы разрешаете полиномы только в развернутой форме?
Адам Яскевич,

Ответы:


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

ах ... но вы пропустили сворачивание «5 * x» в «5x»
Джеймс Карран

Пара проблем: \ ^ должно быть \\ ^, а $ должно быть \ $.
cdmckay

По-прежнему появляется ошибка «неверная escape-последовательность» ... я что-то упустил?
Дэн Бурзо,

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

2
Можно ли использовать предварительно скомпилированный шаблон? Это может быть полезно, если вы много раз заменяете все одним и тем же регулярным выражением.
Qed 05

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

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

обратите внимание, что объединение обеих замен в одном регулярном выражении / замене было бы плохим выбором, потому что более общие выражения, такие как, x^3 - 6 * xне работают.


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, в его нынешнем виде регулярное выражение ожидает пробел перед и после каждого *. Это можно решить в регулярном выражении, но оставим это в качестве упражнения.
Ливен Кеерсмэкерс,

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

3

Если это для какого-либо общего математического выражения и допускаются выражения в скобках, будет очень сложно (возможно, невозможно) сделать это с помощью регулярных выражений.

Если единственные замены - те, которые вы показали, это не так сложно сделать. Сначала *удалите 's, затем используйте захват, как показал Кан Берк Гюдер, чтобы справиться с ^' s.


Да, позже я объяснил в примечании PS, что я использую это для синтаксического анализа базового строкового представления полинома в нечто более удобочитаемое. Спасибо!
Дэн Бурзо,

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

3

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

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


Я понимаю, о чем вы говорите ... это действительно избавит меня от многих страданий, но я стараюсь держать вещи отдельно. Я хотел, чтобы Polynomial был автономным классом, который можно было бы использовать в другом контексте, например в консоли ... но мой подход мог быть неправильным. Что вы думаете?
Дэн Бурзо,

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

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

я сделал новый метод: 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 выдает ошибку для второго параметра: «Недопустимая escape-последовательность»
Дэн Бурзо,

Хммм ... Я тестирую это в 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 голоса. Ваш ответ буквально говорит: «Возможно, это не лучший способ», указывая на то, что в этой теме уже есть лучшие решения.
Эрик Джи

Я не вижу «лучшего» ответа над ним ... Но есть один, который в некоторых случаях лучше внизу.
сергейч

0

Взгляните на antlr4. Это поможет вам продвинуться дальше в создании древовидной структуры, чем только регулярные выражения.

https://github.com/antlr/grammars-v4/tree/master/calculator (Calculator.g4 содержит нужную вам грамматику)

Вкратце, вы определяете грамматику для анализа выражения, используете antlr для генерации Java-кода и добавляете обратные вызовы для обработки оценки при построении дерева.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.