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

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("");
}
Florian
источник
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>");
Hubbison
источник
11
"5 * x^3 - 6 * x^1 + 1".replaceAll("\\W*\\*\\W*","").replaceAll("\\^(\\d+)","<sup>$1</sup>");

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

vit123
источник
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.

cdmckay
источник
Спасибо за совет по импорту. К сожалению, 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);
    }
}
BigGinDaHouse
источник
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);
user5915163
источник
7
Вопрос был из 2009 года, и на него уже есть 8 ответов. Первый ответ получил 82 голоса. Ваш ответ буквально говорит: «Возможно, это не лучший способ», указывая на то, что в этой теме уже есть лучшие решения.
Эрик Джи
Я не вижу «лучшего» ответа над ним ... Но есть один, который в некоторых случаях лучше внизу.
сергейч
0

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

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

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

Джеффри Ричи
источник