Jawa; Ganti string (menggunakan ekspresi reguler)?

129

Sebagai bagian dari proyek untuk sekolah, saya perlu mengganti string dari formulir:

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

menjadi sesuatu seperti:

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

Saya yakin ini bisa dilakukan dengan ekspresi reguler, tetapi saya belum tahu bagaimana melakukannya.

Bisakah Anda membantu saya?

PS Tugas sebenarnya adalah untuk mengimplementasikan aplikasi Java Pemrosesan Polinomial, dan saya menggunakan ini untuk meneruskan polynomial.toString () dari model ke tampilan, dan saya ingin menampilkannya menggunakan tag html dengan cara yang cantik.

Dan Burzo
sumber
2
Permisi, bisa lebih spesifik? Saya tidak mengerti maksud Anda.
Dan Burzo
5
Lelucon lama. codinghorror.com/blog/archives/001016.html memiliki penjelasan.
Michael Myers
1
Oh :) Saya rasa saya benar-benar membaca artikel itu beberapa waktu yang lalu ... Jadi menurut Anda regex bukanlah cara yang tepat untuk kasus saya?
Dan Burzo
Jadi Anda hanya mengizinkan polinomial dalam bentuk yang diperluas?
Adam Jaskiewicz

Jawaban:

176
str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");
Can Berk Güder
sumber
ah ... tapi Anda melewatkan menciutkan "5 * x" menjadi "5x"
James Curran
Masalah pasangan: \ ^ harus \\ ^ dan $ harus \ $.
cdmckay
Masih mendapatkan kesalahan "urutan pelolosan tidak valid" ... apakah saya melewatkan sesuatu?
Dan Burzo
ini memberi saya kesalahan pada parameter kedua: str.replaceAll ("\\ ^ ([0-9] +)", "<sup> \ $ 1 </sup>"); Saya tidak mengerti ... :(
Dan Burzo
2
Apakah mungkin menggunakan pola yang telah dikompilasi sebelumnya? Ini mungkin berguna jika Anda melakukan replaceAll dengan regex yang sama berkali-kali.
qed
38
private String removeScript(String content) {
    Pattern p = Pattern.compile("<script[^>]*>(.*?)</script>",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    return p.matcher(content).replaceAll("");
}
Florian
sumber
8
Ini adalah IMO terbaik, karena menggunakan Regex yang dikompilasi, tetapi objek Pattern harus berupa objek statis.
Marcel Valdez Orozco
Hal yang menyenangkan adalah bahwa replaceAllmetode ini secara implisit melakukannya Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)! Jadi, jika Anda menggunakan kembali pola dengan cara ini, objek yang berlebihan akan dihindari. Lebih lanjut, seperti yang dikatakan @MarcelValdezOrozco, menjadikannya statis akan mencegah pemanggilan kompilasi pola yang tidak perlu. :)
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
sumber
11
"5 * x^3 - 6 * x^1 + 1".replaceAll("\\W*\\*\\W*","").replaceAll("\\^(\\d+)","<sup>$1</sup>");

harap dicatat bahwa menggabungkan kedua pengganti dalam satu regex / pengganti akan menjadi pilihan yang buruk karena ekspresi yang lebih umum seperti x^3 - 6 * xakan gagal.

vit123
sumber
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
}
Lieven Keersmaekers
sumber
1
@Dan: Pastikan Anda memahami apa yang dilakukan regex! Regex berbahaya di tangan orang yang hampir mengenalnya. (Oleh karena itu kutipan yang saya posting.)
Michael Myers
@Dan, sebagaimana berdiri, regex mengharapkan spasi di depan dan setelah setiap *. Ini bisa diselesaikan di regex tapi biarkan itu sebagai latihan.
Lieven Keersmaekers
@Dan. Saya mengubah regex sedikit setelah membuat komentar. Asli adalah: (:? \ D +) * x \ ^ (:? \ D) Baru adalah: (:? \ D +) * x \ ^ (:? \ D +)
Lieven Keersmaekers
3

Jika ini untuk ekspresi matematika umum dan ekspresi tanda kurung diperbolehkan, akan sangat sulit (mungkin tidak mungkin) untuk melakukan ini dengan ekspresi reguler.

Jika satu-satunya penggantinya adalah yang Anda tunjukkan, itu tidak sulit dilakukan. Pertama strip keluar *, kemudian gunakan pengambilan seperti yang ditunjukkan Can Berk Güder untuk menangani ^itu.

Michael Myers
sumber
Ya, saya kemudian menjelaskan dalam catatan PS bahwa saya menggunakan ini untuk mengurai representasi string dasar dari polinomial menjadi sesuatu yang lebih dapat dibaca manusia. Terima kasih!
Dan Burzo
Polinomial semuanya dapat diperluas ke bentuk yang tidak melibatkan ekspresi tanda kurung. Namun, mencocokkan paren sangat menyenangkan, jadi Anda tidak boleh membatasi diri Anda hanya pada bentuk yang diperluas.
Adam Jaskiewicz
3

Apa polinomial Anda? Jika Anda "memproses", saya membayangkan semacam pohon sub-ekspresi yang dihasilkan di beberapa titik, dan akan berpikir bahwa akan lebih mudah menggunakannya untuk menghasilkan string Anda daripada mengurai ulang mentah ekspresi dengan regex.

Hanya melemparkan cara berpikir yang berbeda di luar sana. Saya tidak yakin apa lagi yang terjadi di aplikasi Anda.

Adam Jaskiewicz
sumber
Saya mengerti apa yang Anda katakan ... itu memang akan menghindarkan saya dari banyak penderitaan, tetapi saya mencoba untuk memisahkan hal-hal. Saya ingin Polynomial menjadi Kelas yang berdiri sendiri yang dapat digunakan dalam konteks lain, seperti konsol ... tetapi pendekatan saya mungkin salah. Bagaimana menurut anda?
Dan Burzo
Saya mengerti apa yang kamu maksud. Memasukkan tag html ke dalam Polynomial.toString () jelas melanggar MVC. Saya pikir saya masih akan melakukan hal seperti itu, karena itu benar-benar akan membuat segalanya lebih mudah. Mungkin toHtmlString () atau sesuatu ...
Adam Jaskiewicz
Atau mungkin kelas terpisah yang digunakan Tampilan khusus untuk memformat polinomial? Kemudian kelas Polynomial itu sendiri tidak perlu tahu apa-apa tentang pemformatannya.
Herms
saya membuat metode baru: toHTML (); ketika Anda memikirkannya, toString () dan toHTML () pada dasarnya adalah hal yang sama secara konseptual, kecuali mereka menggunakan aturan yang berbeda untuk pemformatan;
Dan Burzo
Ya, saya tidak terlalu suka pemformatan khusus tampilan ada di objek, tetapi ini akan memungkinkan Anda menggunakan polimorfisme untuk menangani banyak logika daripada pernyataan sakelar raksasa dalam metode utilitas statis. Ketika datang langsung ke sana, toString () juga merupakan pemformatan khusus tampilan ...
Adam Jaskiewicz
1

Coba ini:

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

Pastikan untuk mengimpor java.util.regex.

cdmckay.dll
sumber
Terima kasih atas tip 'impor'. Sayangnya, Eclipse memberi saya kesalahan untuk parameter kedua: "Urutan pelarian tidak valid"
Dan Burzo
Hmmm ... Saya mengujinya di GroovyConsole tetapi tidak di Java. Anda juga harus memastikan bahwa ini semua ada di boilerplate Java (yaitu membuat kelas, dan membuangnya ke metode utama).
cdmckay
String pengganti harus "<sup> $ 1 </sup>" - tanpa garis miring terbalik. Groovy memiliki aturan berbeda tentang garis miring terbalik; Anda harus menguji kode Anda di Java.
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);
    }
}
BigGinDaHouse
sumber
0

Anda akan ingin melihat menangkap dalam ekspresi reguler untuk menangani pembungkusan 3 dalam ^ 3.

Ryan Graham
sumber
0

Coba ini, mungkin bukan cara terbaik. tetapi berhasil

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);
pengguna5915163
sumber
7
Pertanyaannya dari tahun 2009 dan sudah memiliki 8 jawaban. Jawaban pertama memiliki 82 suara. Jawaban Anda secara harfiah mengatakan 'mungkin bukan cara terbaik' yang menunjukkan ada solusi yang lebih baik, yang sudah ada di utas ini.
Eric G
Saya tidak melihat jawaban yang 'lebih baik' di atasnya ... Namun ada satu yang dalam beberapa kasus lebih baik di bawah.
sergeych
0

Lihatlah antlr4. Ini akan membawa Anda lebih jauh dalam membuat struktur pohon daripada ekspresi reguler saja.

https://github.com/antlr/grammars-v4/tree/master/calculator (calculator.g4 berisi tata bahasa yang Anda butuhkan)

Singkatnya, Anda menentukan tata bahasa untuk mengurai ekspresi, menggunakan antlr untuk menghasilkan kode java, dan menambahkan callback untuk menangani evaluasi saat pohon sedang dibuat.

Geoffrey Ritchey
sumber