2012-03-11 37 views
7

Tôi đã vui vẻ chạy Regex replaceAllIn trong một thời gian nhưng đã gặp sự cố khi chuỗi replacement có thứ gì đó trông giống như một regex trong đó. Sau đây minh họa vấn đề (Scala 2.9.1-1). Lưu ý rằng không gian vấn đề thực sự phức tạp hơn nhiều, vì vậy ý ​​tưởng sử dụng một giải pháp đơn giản hơn không thực sự có thể ở được (chỉ để tránh sự không thể tránh khỏi "Tại sao bạn không thử ...": D)scala regex replaceAllIn không thể thay thế khi chuỗi thay thế trông giống như một regex?

val data = "val re = \"\"\"^[^/]*://[^/]*/[^/]*$\"\"\".r" 
val source = """here 
LATEX_THING{abc} 
there""" 
val re = "LATEX_THING\\{abc\\}".r 
println(re.replaceAllIn(source, data)) 

này trình bày với các lỗi sau:

java.lang.IllegalArgumentException: Illegal group reference 

Nếu tôi thay đổi data từ những gì nó là một cái gì đó đơn giản như:

val data = "This will work" 

sau đó tốt mọi thứ đều.

Có vẻ như replaceAllIn bằng cách nào đó đang tìm kiếm chuỗi thứ hai và sử dụng nó làm RE khác để tham khảo những gì được ghi nhớ từ RE đầu tiên ... nhưng tài liệu không nói gì về điều này.

Tôi đang thiếu gì?

chỉnh sửa: Ok, do đó sau khi nhìn vào lớp java.util.regex.Matcher, nó sẽ có vẻ rằng việc sửa chữa dự định là:

re.replaceAllIn(source, java.util.regex.Matcher.quoteReplacement(data)) 

Trả lời

9

Bạn cần phải thoát khỏi $ trong chuỗi thay thế của bạn:

val data = "val re = \"\"\"^[^/]*://[^/]*/[^/]*\\$\"\"\".r" 

Nếu không, nó được hiểu là khởi đầu của tham chiếu nhóm (chỉ có giá trị nếu $ được theo sau bởi một hoặc nhiều chữ số). Xem the documentation cho java.util.regex.Matcher để xem chi tiết hơn:

The replacement string may contain references to subsequences captured during the previous match: Each occurrence of $g will be replaced by the result of evaluating group(g) ... A dollar sign ($) may be included as a literal in the replacement string by preceding it with a backslash (\$).

Update để giải quyết nhận xét và chỉnh sửa trên: Có, bạn có thể sử dụng Matcher.quoteReplacement nếu bạn không làm việc với xâu (hoặc nếu bạn đang có, tôi đoán, nhưng thoát các $ có vẻ dễ dàng hơn trong trường hợp đó), và có ít nhất a chance rằng quoteReplacement sẽ có sẵn như một phương pháp trên scala.util.matching.Regex trong tương lai.

+1

Cảm ơn bạn. Nó không xảy ra với tôi để đi đến các tài liệu Java ... đó là những gì tôi nhận được không bao giờ là một coder Java thực sự, tôi đoán. 'Dữ liệu' đang được đề cập đến thực sự xuất phát từ tệp nguồn Scala. Tôi đoán quy tắc của ngón tay cái là, trừ khi bạn biết chính xác những gì bạn đã có, tiền xử lý nó đầu tiên bằng cách thay thế '$' cho '\ $' và sau đó xử lý nó theo cách bạn muốn. –