Java; Chuỗi thay thế (sử dụng biểu thức chính quy)?


128

Là một phần của dự án cho trường học, tôi cần thay thế một chuỗi từ biểu mẫu:

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

đến một cái gì đó như:

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

Tôi tin rằng điều này có thể được thực hiện với các biểu thức thông thường, nhưng tôi không biết làm thế nào để làm điều đó.

Bạn có thể giúp tôi một tay?

PS Nhiệm vụ thực tế là triển khai ứng dụng Java Xử lý đa thức và tôi đang sử dụng ứng dụng này để chuyển đa thức.toString () từ mô hình sang dạng xem và tôi muốn hiển thị nó bằng cách sử dụng các thẻ html theo cách khá hay.


2
Xin lỗi, bạn có thể cụ thể hơn không? Tôi không hiểu ý của bạn.
Dan Burzo

5
Trò đùa cũ. mã hóa kinh dị.com / blog / archives / 001016.html có một lời giải thích.
Michael Myers

1
Ồ :) Tôi nghĩ rằng tôi thực sự đã đọc bài báo đó một thời gian trước ... Vì vậy, bạn đang đề xuất regex không phải là cách để đi trong trường hợp của tôi?
Dan Burzo

Vì vậy, bạn chỉ cho phép đa thức ở dạng mở rộng?
Adam Jaskiewicz

Câu trả lời:


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

à ... nhưng bạn đã bỏ lỡ việc thu gọn "5 * x" thành "5x"
James Curran

Vấn đề về cặp đôi: \ ^ cần phải là ^ ^ và $ cần phải là \ $.
cdmckay

Vẫn nhận được lỗi "chuỗi thoát không hợp lệ" ... tôi có thiếu gì không?
Dan Burzo

điều này mang lại cho tôi một lỗi ở tham số thứ hai: str.replaceAll ("\\ ^ ([0-9] +)", "<sup> \ $ 1 </ sup>"); Tôi không hiểu được ... :(
Dan Burzo

2
Có thể sử dụng một mẫu được biên dịch trước? Điều này có thể hữu ích nếu bạn thay thế All bằng cùng một biểu thức chính quy nhiều lần.
qed

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

8
Đây là IMO tốt nhất, vì nó sử dụng Regex đã biên dịch, nhưng đối tượng Mẫu phải là một đối tượng tĩnh.
Marcel Valdez Orozco

Điều thú vị là replaceAllphương pháp ngầm làm Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)! Vì vậy, nếu bạn sử dụng lại mẫu theo cách này, các đối tượng dư thừa sẽ tránh được. Hơn nữa, như @MarcelValdezOrozco nói, làm cho nó tĩnh sẽ ngăn chặn các yêu cầu biên dịch mẫu không cần thiết. :)
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: Hãy chắc chắn bạn hiểu regex đang làm gì! Regexes là nguy hiểm trong tay của những người gần như biết chúng. (Do đó, trích dẫn tôi đã đăng.)
Michael Myers

@Dan, vì nó đứng, regex mong đợi một khoảng trống ở phía trước và sau mỗi *. Điều này có thể được giải quyết trong regex nhưng hãy để nó như một bài tập.
Lieven Keersmaekers

@Dan. Tôi đã thay đổi regex một chút sau khi tạo các bình luận. Ban đầu là: (: \ d +?) * X \ ^ (: \ d?) Mới là: (: \ d +?) * X \ ^ (: \ d +)
Lieven Keersmaekers

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

xin lưu ý rằng việc tham gia cả hai thay thế trong một regex / thay thế duy nhất sẽ là một lựa chọn tồi vì các biểu thức tổng quát hơn như x^3 - 6 * xsẽ thất bại.


3

Nếu điều này là cho bất kỳ biểu thức toán học chung nào và các biểu thức phụ huynh được cho phép, sẽ rất khó (có lẽ là không thể) để làm điều này với các biểu thức thông thường.

Nếu thay thế duy nhất là những gì bạn đã cho thấy, nó không khó để làm. Trước tiên hãy loại bỏ *, sau đó sử dụng chức năng chụp như Can Berk Güder hiển thị để xử lý ^.


Vâng, sau đó tôi đã giải thích trong một ghi chú PS rằng tôi đang sử dụng điều này để phân tích một chuỗi đại diện cơ bản của đa thức thành một thứ gì đó dễ đọc hơn cho con người. Cảm ơn!
Dan Burzo

Đa thức tất cả có thể được mở rộng thành một hình thức không có biểu thức chính. Mặc dù vậy, kết hợp Paren rất thú vị, vì vậy bạn không nên giới hạn bản thân chỉ ở dạng mở rộng.
Adam Jaskiewicz

3

Đa thức của bạn là gì? Nếu bạn đang "xử lý" nó, tôi đang hình dung một số loại biểu thức con được tạo ra tại một thời điểm nào đó và sẽ nghĩ rằng việc sử dụng chuỗi đó để tạo chuỗi của bạn sẽ đơn giản hơn nhiều so với phân tích lại thô biểu thức với một regex.

Chỉ cần ném một cách suy nghĩ khác ra khỏi đó. Tôi không chắc những gì khác đang diễn ra trong ứng dụng của bạn.


Tôi hiểu những gì bạn đang nói ... điều đó thực sự sẽ giúp tôi rất nhiều đau khổ, nhưng tôi đang cố giữ mọi thứ tách biệt. Tôi muốn Polynomial là một Class độc lập có thể được sử dụng trong bối cảnh khác, chẳng hạn như bảng điều khiển ... nhưng cách tiếp cận của tôi có thể sai. Bạn nghĩ sao?
Dan Burzo

Tôi hiểu ý bạn là gì. Việc kết hợp các thẻ html vào Polynomial.toString () chắc chắn sẽ phá vỡ MVC. Tôi nghĩ rằng tôi vẫn sẽ làm một cái gì đó như vậy, mặc dù, bởi vì nó thực sự sẽ làm cho mọi thứ dễ dàng hơn. Có lẽ toHtmlString () hoặc một cái gì đó ...
Adam Jaskiewicz

Hoặc có thể một lớp riêng biệt mà Chế độ xem sử dụng cụ thể để định dạng đa thức? Sau đó, lớp Polynomial tự nó không cần biết gì về định dạng.
Herms

tôi đã thực hiện một phương thức mới: toHTML (); Khi bạn nghĩ về nó, toString () và toHTML () về cơ bản là giống nhau về mặt khái niệm, ngoại trừ chúng sử dụng các quy tắc khác nhau để định dạng;
Dan Burzo

Vâng, tôi không thực sự thích định dạng dành riêng cho chế độ xem trong đối tượng, nhưng nó sẽ cho phép bạn sử dụng đa hình để xử lý nhiều logic hơn là một câu lệnh chuyển đổi khổng lồ trong phương thức tiện ích tĩnh. Khi nói đến nó, toString () cũng là định dạng dành riêng cho chế độ xem ...
Adam Jaskiewicz

1

Thử cái này:

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

Hãy chắc chắn để nhập java.util.regex.


Cảm ơn vì mẹo 'nhập khẩu'. Thật không may, Eclipse cho tôi một lỗi cho tham số thứ hai: "Chuỗi thoát không hợp lệ"
Dan Burzo

Hmmm ... Tôi đã thử nghiệm nó trong GroovyConsole nhưng không phải Java. Bạn cũng phải đảm bảo rằng đây là tất cả trong bản tóm tắt Java (nghĩa là tạo một lớp và ném nó vào một phương thức chính).
cdmckay

Chuỗi thay thế phải là "<sup> $ 1 </ sup>" - không có dấu gạch chéo ngược. Groovy có các quy tắc khác nhau về dấu gạch chéo ngược; bạn nên kiểm tra mã của mình bằng 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);
    }
}

0

Bạn sẽ muốn xem xét việc chụp trong regex để xử lý gói 3 trong ^ 3.


0

Hãy thử điều này, có thể không phải là cách tốt nhất. nhưng nó đã có tác dụng

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
Câu hỏi là từ năm 2009 và đã có 8 câu trả lời. Câu trả lời đầu tiên có 82 phiếu. Câu trả lời của bạn theo nghĩa đen là 'có thể không phải là cách tốt nhất' chỉ ra rằng có những giải pháp tốt hơn, đã có, trong chủ đề này.
Eric G

Tôi thấy không có câu trả lời 'tốt hơn' ở trên nó ... Tuy nhiên, có một câu mà trong một số trường hợp tốt hơn bên dưới.
sergeych

0

Hãy nhìn vào antlr4. Nó sẽ giúp bạn đi xa hơn trong việc tạo cấu trúc cây hơn là các biểu thức thông thường một mình.

https://github.com/antlr/grammars-v4/tree/master/calculator (Calculator.g4 chứa ngữ pháp bạn cần)

Tóm lại, bạn xác định ngữ pháp để phân tích một biểu thức, sử dụng antlr để tạo mã java và thêm các cuộc gọi lại để xử lý đánh giá khi cây đang được xây dựng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.