Java; Dize değiştirme (normal ifadeler kullanarak)?


129

Bir okul projesinin parçası olarak, şu formdaki bir dizeyi değiştirmem gerekiyor:

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

gibi bir şeye:

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

Bunun normal ifadelerle yapılabileceğine inanıyorum, ancak henüz nasıl yapılacağını bilmiyorum.

Bana yardım eder misin?

PS Asıl atama, bir Polinom İşleme Java uygulaması uygulamaktır ve bunu polinomial.toString () 'i modelden görünüme geçirmek için kullanıyorum ve bunu html etiketlerini kullanarak güzel bir şekilde görüntülemek istiyorum.


2
Affedersiniz, daha açık konuşur musunuz? Ne demek istediğini anlamıyorum.
Dan Burzo

5
Eski bir şaka. codinghorror.com/blog/archives/001016.html'de bir açıklama var.
Michael Myers

1
Oh :) Sanırım bir süre önce bu makaleyi okudum ... Yani benim durumumda regex'in uygulanacak yol olmadığını mı söylüyorsunuz?
Dan Burzo

Yani polinomlara sadece genişletilmiş formda izin veriyorsunuz?
Adam Jaskiewicz

Yanıtlar:


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

ah ... ama "5 * x" i "5x" e indirmeyi kaçırdınız
James Curran

Birkaç problem: \ ^ \ ^ olmalı \\ ^ ve $ \ $ olmalı.
cdmckay

Hala "geçersiz kaçış dizisi" hatası alıyorum ... bir şey mi eksik?
Dan Burzo

bu bana ikinci parametrede bir hata veriyor: str.replaceAll ("\\ ^ ([0-9] +)", "<sup> \ $ 1 </sup>");
Anlamıyorum

2
Önceden derlenmiş bir kalıp kullanmak mümkün mü? Aynı normal ifadeyi birçok kez değiştirirseniz bu yararlı olabilir.
2014

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

8
Bu en iyi IMO'dur, çünkü derlenmiş bir Regex kullanır, ancak Pattern nesnesi statik bir nesne olmalıdır.
Marcel Valdez Orozco

Eğlenceli olan şey, replaceAllyöntemin dolaylı olarak yapmasıdır Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)! Bu nedenle, deseni bu şekilde tekrar kullanırsanız, gereksiz nesnelerden kaçınılacaktır. Ayrıca, @MarcelValdezOrozco'nun dediği gibi, statik hale getirmek, gereksiz desen derleme çağrılarını önleyecektir. :)
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>");

Lütfen, tek bir normal ifadede / değiştirmede her iki değiştirmeyi de birleştirmenin kötü bir seçim olacağını unutmayın, çünkü gibi daha genel ifadeler x^3 - 6 * xbaşarısız olur.


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: Normal ifadenin ne yaptığını anladığınızdan emin olun! Normal ifadeler, onları neredeyse tanıyan insanların elinde tehlikelidir . (Bu yüzden yazdığım alıntı.)
Michael Myers

@Dan, olduğu gibi, normal ifade her * 'in önünde ve sonrasında bir boşluk bekler. Bu normal ifadede çözülebilir ama bunu bir egzersiz olarak bırakalım.
Lieven Keersmaekers

@Dan. Yorumları oluşturduktan sonra normal ifadeyi biraz değiştirdim. Orijinal: (:? \ D +) * x \ ^ (:? \ D) Yeni: (:? \ D +) * x \ ^ (:? \ D +)
Lieven Keersmaekers

3

Bu, herhangi bir genel matematik ifadesi içinse ve parantez içindeki ifadelere izin veriliyorsa, bunu normal ifadelerle yapmak çok zor (belki imkansız) olacaktır.

Gösterdiğiniz tek değişiklik varsa, yapmak o kadar da zor değil. Önce *soyun, sonra Can Berk Güder'in gösterdiği gibi yakalamayı kullanın ^.


Evet, daha sonra bir PS notunda, bunu bir polinomun temel bir dize temsilini daha insan tarafından okunabilir bir şeye ayrıştırmak için kullandığımı açıkladım. Teşekkürler!
Dan Burzo

Polinomların tümü, parantez içi ifadeler içermeyen bir biçime genişletilebilir. Paren eşleme çok eğlencelidir, bu nedenle kendinizi yalnızca genişletilmiş biçimle sınırlamamalısınız.
Adam Jaskiewicz

3

Polinomun nedir? Eğer onu "işliyorsanız", bir noktada bir tür alt ifade ağacının üretildiğini düşünüyorum ve bunu dizenizi oluşturmak için kullanmanın ham olanı yeniden ayrıştırmaktan çok daha kolay olacağını düşünürdüm. normal ifadeli ifade.

Sadece farklı bir düşünce tarzı ortaya atıyorum. Uygulamanızda başka neler olduğundan emin değilim.


Ne dediğini anlıyorum ... bu gerçekten beni çok fazla acı çekmekten kurtarır, ama ben her şeyi ayrı tutmaya çalışıyorum. Polinomun konsol gibi başka bağlamlarda kullanılabilecek bağımsız bir Sınıf olmasını istedim ... ancak yaklaşımım yanlış olabilir. Ne düşünüyorsun?
Dan Burzo

Ne demek istediğini anlıyorum. Html etiketlerini Polynomial.toString () içine dahil etmek MVC'yi kesinlikle bozuyor. Sanırım yine de böyle bir şey yapardım çünkü bu işleri gerçekten kolaylaştırırdı. Belki toHtmlString () veya başka bir şey ...
Adam Jaskiewicz

Veya View'un özellikle polinomu biçimlendirmek için kullandığı ayrı bir sınıf mı? O zaman Polinom sınıfının kendisinin biçimlendirme hakkında hiçbir şey bilmesine gerek kalmaz.
Herms

yeni bir yöntem yaptım: toHTML (); düşündüğünüzde, toString () ve toHTML () temelde kavramsal olarak aynı şeydir, tek fark biçimlendirme için farklı kurallar kullanırlar;
Dan Burzo

Evet, biçimlendirme görünüme özgüdür olduğu pek hoşlanmadığını içinde nesne, ancak statik yarar yönteminde mantığı çok ziyade dev switch deyimi ile başa çıkmak için çok biçimlilik kullanmak için izin verecek.
Tamamen

1

Bunu dene:

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

Java.util.regex'i içe aktardığınızdan emin olun.


"İçe aktarma" ipucu için teşekkürler. Maalesef Eclipse bana ikinci parametre için bir hata veriyor: "Geçersiz kaçış dizisi"
Dan Burzo,

Hmmm ... GroovyConsole'da test ediyorum ama Java'da değil. Ayrıca bunların hepsinin Java standart metninde olduğundan emin olmalısınız (yani bir sınıf oluşturun ve onu bir ana yönteme atın).
cdmckay

Yerini alan dize "<sup> $ 1 </sup>" olmalıdır - ters eğik çizgi yok. Groovy'nin ters eğik çizgiler hakkında farklı kuralları vardır; kodunuzu Java'da test etmelisiniz.
Alan Moore

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'e sarmayı işlemek için normal ifadede yakalamaya bakmak isteyeceksiniz.


0

Bunu deneyin, en iyi yol olmayabilir. ama işe yarıyor

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
Soru 2009'dandı ve şimdiden 8 cevabı var. İlk cevapta 82 oy var. Cevabınız kelimenin tam anlamıyla 'en iyi yol olmayabilir' diyor ve bu konu başlığında zaten var olan daha iyi çözümler olduğunu gösteriyor.
Eric G

Yukarıda 'daha iyi' bir cevap göremiyorum ... Yine de, bazı durumlarda aşağıda daha iyi olan bir cevap var.
sergeych

0

Antlr4'e bir göz atın. Bir ağaç yapısı oluşturmada sizi tek başına normal ifadelerden çok daha ileriye götürecektir.

https://github.com/antlr/grammars-v4/tree/master/calculator (calculator.g4 ihtiyacınız olan grameri içerir)

Özetle, bir ifadeyi ayrıştırmak için dilbilgisini tanımlar, java kodu oluşturmak için antlr kullanır ve ağaç inşa edilirken değerlendirmeyi işlemek için geri çağırmalar eklersiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.