Java; การแทนที่สตริง (โดยใช้นิพจน์ทั่วไป)?


129

เป็นส่วนหนึ่งของโครงการสำหรับโรงเรียนฉันต้องเปลี่ยนสตริงจากแบบฟอร์ม:

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

เพื่อสิ่งที่ชอบ:

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

ฉันเชื่อว่าสิ่งนี้สามารถทำได้ด้วยนิพจน์ทั่วไป แต่ฉันยังไม่รู้ว่าจะทำอย่างไร

ช่วยยืมมือหน่อยได้ไหม

ป.ล. การกำหนดจริงคือการใช้แอปพลิเคชัน Polynomial Processing Java และฉันใช้สิ่งนี้เพื่อส่ง polynomial.toString () จากโมเดลไปยังมุมมองและฉันต้องการแสดงโดยใช้แท็ก html ในทางที่ดี


2
ขอโทษนะคุณสามารถเจาะจงมากขึ้นได้ไหม ฉันไม่เข้าใจว่าคุณหมายถึงอะไร
Dan Burzo

5
เรื่องตลกเก่า codinghorror.com/blog/archives/001016.htmlมีคำอธิบาย
Michael Myers

1
โอ้ :) ฉันคิดว่าฉันอ่านบทความนั้นมาแล้วจริงๆ ... ดังนั้นคุณกำลังแนะนำว่า regex ไม่ใช่วิธีที่จะไปในกรณีของฉัน?
Dan Burzo

คุณอนุญาตเฉพาะพหุนามในรูปแบบขยาย?
Adam Jaskiewicz

คำตอบ:


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

อา ... แต่คุณพลาดการยุบ "5 * x" เป็น "5x"
James Curran

ปัญหาคู่: \ ^ ต้องเป็น \\ ^ และ $ ต้องเป็น \ $
cdmckay

ยังคงได้รับข้อผิดพลาด "ลำดับการหลีกเลี่ยงไม่ถูกต้อง" ... ฉันขาดอะไรไปหรือเปล่า
Dan Burzo

สิ่งนี้ทำให้ฉันมีข้อผิดพลาดที่พารามิเตอร์ที่สอง: str.replaceAll ("\\ ^ ([0-9] +)", "<sup> \ $ 1 </sup>"); ฉันไม่เข้าใจ ... :(
Dan Burzo

2
เป็นไปได้ไหมที่จะใช้รูปแบบที่รวบรวมไว้ล่วงหน้า สิ่งนี้อาจมีประโยชน์หากคุณทำการแทนที่ทั้งหมดด้วย regex เดียวกันหลาย ๆ ครั้ง
qed

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 ควรเป็นวัตถุคงที่
Marcel Valdez Orozco

สิ่งที่สนุกก็คือ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>");

โปรดทราบว่าการเข้าร่วมการแทนที่ทั้งสองใน regex / การแทนที่ครั้งเดียวอาจเป็นทางเลือกที่ไม่ดีเนื่องจากนิพจน์ทั่วไปเช่น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
@ แดน: ต้องแน่ใจว่าคุณเข้าใจว่า regex กำลังทำอะไรอยู่! Regexes เป็นอันตรายในมือของคนที่เกือบจะรู้จักพวกเขา (ดังนั้นคำพูดที่ฉันโพสต์)
Michael Myers

@ แดนตามที่ระบุไว้ regex คาดว่าจะมีช่องว่างด้านหน้าและหลังแต่ละอัน * สิ่งนี้สามารถแก้ไขได้ใน regex แต่ขอปล่อยให้เป็นแบบฝึกหัด
Lieven Keersmaekers

@Dan ฉันเปลี่ยน regex เล็กน้อยหลังจากสร้างความคิดเห็น เดิมคือ: (:? \ d +) * x \ ^ (:? \ d) ใหม่คือ: (:? \ d +) * x \ ^ (:? \ d +)
Lieven Keersmaekers

3

หากเป็นไปได้สำหรับนิพจน์ทางคณิตศาสตร์ทั่วไปและอนุญาตให้ใช้นิพจน์ทั่วไปได้การทำเช่นนี้กับนิพจน์ทั่วไปจะเป็นเรื่องยากมาก (อาจเป็นไปไม่ได้)

หากการเปลี่ยนเพียงอย่างเดียวเป็นของที่คุณแสดงก็ไม่ยากที่จะทำ ครั้งแรกที่ดึงออกจาก*'s แล้วใช้จับเช่น Can Berk Güderแสดงให้เห็นในการจัดการ^ของ


ใช่ฉันได้อธิบายในบันทึก PS ในภายหลังว่าฉันกำลังใช้สิ่งนี้เพื่อแยกวิเคราะห์การแสดงสตริงพื้นฐานของพหุนามให้เป็นสิ่งที่มนุษย์อ่านได้มากขึ้น ขอบคุณ!
Dan Burzo

พหุนามทั้งหมดสามารถขยายเป็นรูปแบบที่ไม่มีนิพจน์วงเล็บ อย่างไรก็ตามการจับคู่พาเรนเป็นเรื่องสนุกมากดังนั้นคุณไม่ควร จำกัด ตัวเองให้อยู่ในรูปแบบที่ขยายเท่านั้น
Adam Jaskiewicz

3

พหุนามของคุณคืออะไร? หากคุณกำลัง "ประมวลผล" อยู่ฉันกำลังจินตนาการถึงโครงสร้างของนิพจน์ย่อยบางประเภทที่ถูกสร้างขึ้นในบางจุดและคิดว่าการใช้สตริงนั้นจะง่ายกว่าการแยกวิเคราะห์ข้อมูลดิบอีกครั้ง นิพจน์ด้วยนิพจน์ทั่วไป

เพียงแค่โยนวิธีคิดที่แตกต่างออกไป ฉันไม่แน่ใจว่ามีอะไรเกิดขึ้นอีกในแอปของคุณ


ฉันเข้าใจในสิ่งที่คุณพูด ... นั่นจะทำให้ฉันทุกข์ทรมานมาก แต่ฉันพยายามแยกสิ่งต่างๆออกจากกัน ฉันต้องการให้พหุนามเป็นคลาสแบบสแตนด์อะโลนที่สามารถใช้ในบริบทอื่น ๆ เช่นคอนโซล ... แต่แนวทางของฉันอาจผิด คุณคิดอย่างไร?
Dan Burzo

ฉันเข้าใจว่าคุณหมายถึงอะไร การรวมแท็ก html เข้ากับ Polynomial.toString () เป็นการทำลาย MVC อย่างแน่นอน ฉันคิดว่าฉันจะยังคงทำอะไรแบบนั้นอยู่เพราะมันจะทำให้ง่ายขึ้นจริงๆ บางที toHtmlString () หรือบางอย่าง ...
Adam Jaskiewicz

หรืออาจจะเป็นคลาสแยกต่างหากที่ View ใช้สำหรับการจัดรูปแบบพหุนามโดยเฉพาะ? จากนั้นคลาสพหุนามเองก็ไม่จำเป็นต้องรู้อะไรเกี่ยวกับการจัดรูปแบบ
สมุนไพร

ฉันสร้างวิธีการใหม่: toHTML (); เมื่อคุณคิดเกี่ยวกับมัน toString () และ toHTML () โดยพื้นฐานแล้วเป็นสิ่งเดียวกันในแนวความคิดยกเว้นว่าพวกเขาใช้กฎที่แตกต่างกันสำหรับการจัดรูปแบบ
Dan Burzo

ใช่ฉันไม่ชอบที่การจัดรูปแบบเฉพาะมุมมองอยู่ในวัตถุ แต่จะช่วยให้คุณใช้ความหลากหลายในการจัดการกับตรรกะจำนวนมากแทนที่จะเป็นคำสั่งสวิตช์ยักษ์ในวิธียูทิลิตี้แบบคงที่ เมื่อพูดถึงมันแล้ว toString () ยังเป็นการจัดรูปแบบเฉพาะมุมมอง ...
Adam Jaskiewicz

1

ลองสิ่งนี้:

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

อย่าลืมนำเข้า java.util.regex


ขอบคุณสำหรับเคล็ดลับ "นำเข้า" ขออภัย Eclipse ทำให้ฉันมีข้อผิดพลาดสำหรับพารามิเตอร์ที่สอง: "ลำดับการหลีกเลี่ยงไม่ถูกต้อง"
Dan Burzo

อืม ... ฉันทดสอบใน GroovyConsole แต่ไม่ใช่ Java คุณต้องตรวจสอบให้แน่ใจว่าทั้งหมดนี้อยู่ใน Java สำเร็จรูป (เช่นสร้างคลาสและโยนไปในเมธอดหลัก)
cdmckay

สตริงแทนที่ควรเป็น "<sup> $ 1 </sup>" - ไม่มีแบ็กสแลช Groovy มีกฎที่แตกต่างกันเกี่ยวกับแบ็กสแลช คุณควรทดสอบโค้ดของคุณใน 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

ลองวิธีนี้อาจไม่ใช่วิธีที่ดีที่สุด แต่มันใช้งานได้

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 โหวต คำตอบของคุณระบุว่า 'อาจไม่ใช่วิธีที่ดีที่สุด' โดยระบุว่ามีวิธีแก้ปัญหาที่ดีกว่าซึ่งมีอยู่แล้วในชุดข้อความนี้
Eric G

ฉันไม่เห็นคำตอบที่ 'ดีกว่า' ด้านบน ... มีข้อหนึ่งที่ในบางกรณีดีกว่าด้านล่างนี้
sergeych

0

ลองดูที่ antlr4 มันจะช่วยให้คุณสร้างโครงสร้างต้นไม้ได้ไกลขึ้นกว่านิพจน์ทั่วไปเพียงอย่างเดียว

https://github.com/antlr/grammars-v4/tree/master/calculator (เครื่องคิดเลข.g4มีไวยากรณ์ที่คุณต้องการ)

สรุปได้ว่าคุณกำหนดไวยากรณ์เพื่อแยกวิเคราะห์นิพจน์ใช้ antlr เพื่อสร้างโค้ด java และเพิ่มการเรียกกลับเพื่อจัดการการประเมินผลเมื่อมีการสร้างแผนผัง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.