Java Regex thay thế bằng Capturing Group


77

Có cách nào để thay thế regexp bằng nội dung đã sửa đổi của nhóm capture không?

Thí dụ:

Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher(text);
resultString = regexMatcher.replaceAll("$1"); // *3 ??

Và tôi muốn thay thế tất cả các lần xuất hiện bằng $ 1 nhân với 3.

biên tập:

Có vẻ như có gì đó không ổn :(

Nếu tôi sử dụng

Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher("12 54 1 65");
try {
    String resultString = regexMatcher.replaceAll(regexMatcher.group(1));
} catch (Exception e) {
    e.printStackTrace();
}

Nó ném IllegalStateException: Không tìm thấy kết quả phù hợp

Nhưng

Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher("12 54 1 65");
try {
    String resultString = regexMatcher.replaceAll("$1");
} catch (Exception e) {
    e.printStackTrace();
}

hoạt động tốt, nhưng tôi không thể thay đổi $ 1 :(

biên tập:

Bây giờ, nó đang hoạt động :)


bằng cách làm việc trực tiếp trên một chuỗi, cuối cùng chúng tôi đã có được điều này
Aquarius Power

Câu trả lời:


81

Làm thế nào về:

if (regexMatcher.find()) {
    resultString = regexMatcher.replaceAll(
            String.valueOf(3 * Integer.parseInt(regexMatcher.group(1))));
}

Để có được trận đấu đầu tiên, hãy sử dụng #find(). Sau đó, bạn có thể sử dụng #group(1)để tham chiếu đến trận đấu đầu tiên này và thay thế tất cả các trận đấu bằng giá trị maches đầu tiên nhân với 3.

Và trong trường hợp bạn muốn thay thế từng trận đấu bằng giá trị của trận đấu đó nhân với 3:

    Pattern p = Pattern.compile("(\\d{1,2})");
    Matcher m = p.matcher("12 54 1 65");
    StringBuffer s = new StringBuffer();
    while (m.find())
        m.appendReplacement(s, String.valueOf(3 * Integer.parseInt(m.group(1))));
    System.out.println(s.toString());

Bạn có thể muốn xem qua Matchertài liệu của , nơi này và nhiều thứ khác được đề cập chi tiết.


10
có nhưng bạn mất chuỗi ban đầu. nếu nó là "a 1 2 3", bạn sẽ không có a
Jasper Floor

20
Điều này khá hữu ích! Một điều bổ sung là nếu kết quả phù hợp của bạn với một văn bản và kết quả phù hợp của bạn không ở cuối, bạn sẽ cần gọi (các) m.appendTail;
meo,

Hãy cẩn thận khi tìm các nhóm có văn bản tĩnh xung quanh như Pattern.compile ("var myVar = \" (. *) \ ";"); - Nó sẽ thay thế tất cả tìm thấy không chỉ nhóm. xem thêm liên kết của John O.
Manuel Manhart,

@ ManuelM.Bạn có thể dễ dàng bỏ qua vấn đề đó bằng cách sử dụng các khẳng định tích cực về cái nhìn trước và sau thay vì văn bản tĩnh. Bằng cách đó, những bộ phận đó sẽ không bị thay thế bởi trình kết hợp.
klaar

Cảm ơn câu trả lời tuyệt vời, bạn đã tìm ra phần hữu ích nhất của ví dụ về hệ số giá trị đó! Điều này làm cho nó rất rõ ràng với tôi! @mezzie Bổ sung rất tốt! Mặc dù nó có trong tài liệu Java java.util.regex.Matcher, nhưng đối với những người chỉ tham khảo bài đăng SO này, nó sẽ rất hữu ích. :)
varun

11

câu trả lời của bá tước cung cấp cho bạn giải pháp, nhưng tôi nghĩ rằng tôi sẽ thêm những gì vấn đề đang gây ra cho bạn IllegalStateException. Bạn đang gọi group(1)mà không phải gọi trước một thao tác khớp (chẳng hạn như find()). Điều này không cần thiết nếu bạn chỉ đang sử dụng $1vì đây replaceAll()là hoạt động phù hợp.


5

Java 9 cung cấp một hàm Matcher.replaceAll()chấp nhận một hàm thay thế:

resultString = regexMatcher.replaceAll(
        m -> String.valueOf(Integer.parseInt(m.group()) * 3));

1

Nguồn: java-implement-of-rubys-gsub

Sử dụng:

// Rewrite an ancient unit of length in SI units.
String result = new Rewriter("([0-9]+(\\.[0-9]+)?)[- ]?(inch(es)?)") {
    public String replacement() {
        float inches = Float.parseFloat(group(1));
        return Float.toString(2.54f * inches) + " cm";
    }
}.rewrite("a 17 inch display");
System.out.println(result);

// The "Searching and Replacing with Non-Constant Values Using a
// Regular Expression" example from the Java Almanac.
result = new Rewriter("([a-zA-Z]+[0-9]+)") {
    public String replacement() {
        return group(1).toUpperCase();
    }
}.rewrite("ab12 cd efg34");
System.out.println(result);

Thực hiện (thiết kế lại):

import static java.lang.String.format;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class Rewriter {
    private Pattern pattern;
    private Matcher matcher;

    public Rewriter(String regularExpression) {
        this.pattern = Pattern.compile(regularExpression);
    }

    public String group(int i) {
        return matcher.group(i);
    }

    public abstract String replacement() throws Exception;

    public String rewrite(CharSequence original) {
        return rewrite(original, new StringBuffer(original.length())).toString();
    }

    public StringBuffer rewrite(CharSequence original, StringBuffer destination) {
        try {
            this.matcher = pattern.matcher(original);
            while (matcher.find()) {
                matcher.appendReplacement(destination, "");
                destination.append(replacement());
            }
            matcher.appendTail(destination);
            return destination;
        } catch (Exception e) {
            throw new RuntimeException("Cannot rewrite " + toString(), e);
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(pattern.pattern());
        for (int i = 0; i <= matcher.groupCount(); i++)
            sb.append(format("\n\t(%s) - %s", i, group(i)));
        return sb.toString();
    }
}
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.