2015-05-11 31 views
10

Tôi có chuỗi được tạo từ kiểu bàn phím người dùng, vì vậy nó có thể chứa '\b' ký tự (dấu cách).Java regex - xóa các ký tự theo sau là b (backspace)

Tôi muốn xóa chuỗi, vì vậy nó sẽ không chứa các ký tự '\b', cũng như các ký tự mà chúng được dùng để xóa. Ví dụ, chuỗi:

String str = "\bHellow\b world!!!\b\b\b."; 

nên được in như:

Hello world. 

Tôi đã thử một vài điều với replaceAll, và những gì tôi có bây giờ là:

System.out.println(str.replaceAll("^\b+|.\b+", "")); 

nào in :

Xin chào thế giới !!.

Đơn '\b' được xử lý tốt, nhưng bội số của nó bị bỏ qua.

Vì vậy, tôi có thể giải quyết nó bằng regex của Java không?

EDIT:

Tôi đã thấy this câu trả lời, nhưng nó dường như không áp dụng cho replaceAll java của.
Có lẽ tôi đang thiếu một cái gì đó với chuỗi đúng nguyên văn ...

+0

Bạn in chuỗi này để lấy '\ b' ở đầu ra như thế nào? – anubhava

+0

Bàn điều khiển của Eclipse ... nhưng tôi cũng chuyển nó trong XML-RPC và nó không thành công vì nó là một ký tự XML không hợp lệ ... – Elist

+0

Tôi chỉ thấy 'Hellow world !!! 'trên bàn điều khiển Eclipse của tôi mà không có' \ b' hiển thị – anubhava

Trả lời

5

Không thể thực hiện trong một lần trừ khi có giới hạn thực tế về số lượng không gian liên tiếp (không có) và có đảm bảo (không có) không có " thêm "khoảng trống mà không có ký tự trước để xóa.

này không được công việc (đó là chỉ có 2 dòng nhỏ):

while (str.contains("\b")) 
    str = str.replaceAll("^\b+|[^\b]\b", ""); 

này xử lý các trường hợp cạnh của đầu vào như "x\b\by" trong đó có một phím lùi thêm vào lúc bắt đầu, cần được tỉa từng là một tiêu thụ đầu tiên số x, chỉ để lại "y".

+0

Cảm ơn, tôi sẽ áp dụng cách tiếp cận này . Sẽ chấp nhận câu trả lời này (nếu không ai khác có một phép thuật tinh khiết Regex để đánh bại điều này ...) – Elist

+1

Nó chỉ cần một sửa chữa đơn giản. nếu đầu vào là '\ bbbbbHellow \ b world !!! \ b \ b \ b.' nó sẽ có kết quả của' Hello world !!. 'mà tôi nghĩ là không mong đợi và sẽ cho chúng ta một đầu ra của 'bbbbHello world thay vào đó. Chỉ cần loại bỏ định lượng lúc đầu hoặc tạo '\ b' một nhóm. –

+0

@GarisMSuero - Ví dụ của bạn in 'bbbbHello world.' như mong đợi. – Elist

0

Nếu tôi hiểu câu hỏi một cách chính xác, đây là giải pháp cho câu hỏi của bạn:

String str = "\bHellow\b world!!!\b\b\b."; 
System.out.println(str.replace(".?\\\b", "")); 
+1

Điều này không hoạt động ... – Elist

+0

Bạn không làm việc này. Anh ta muốn mô phỏng phím xóa lùi trên mọi '/ b' được tìm thấy. –

0

Đây là một câu đố tốt đẹp. Tôi nghĩ rằng bạn có thể sử dụng một regex để loại bỏ cùng một số nhân vật lặp đi lặp lại giống hệt nhau và \b s (ví dụ: cho chuỗi đầu vào cụ thể của bạn):

String str = "\bHellow\b world!!!\b\b\b."; 
System.out.println(str.replaceAll("^\b+|(?:([^\b])(?=\\1*+(\\2?+\b)))+\\2", "")); 

Đây là một sự thích nghi của How can we match a^n b^n with Java regex?.

Xem IDEONE demo, tại đây tôi đã thêm .replace("\b","<B>")); để xem có bất kỳ \b s nào không.

Output:

Hello world. 

Một giải pháp regex chỉ chung chung là ngoài phạm vi regex ... cho bây giờ.

+0

Bản thân chuỗi chứa '.', Mẫu không – Elist

+0

Có, đó là lý do tại sao tôi xóa nó khỏi mẫu. –

+0

Thú vị, nhưng vẫn in Hellow \ b thế giới. trong bảng điều khiển của tôi – Elist

3

Vấn đề bạn đang cố gắng để giải quyết không thể được giải quyết với đơn biểu thức chính quy. Vấn đề ở đây là ngữ pháp, tạo ra ngôn ngữ {any_symbol}*{any_symbol}^n{\b}^n (trường hợp đặc biệt của dữ liệu nhập của bạn) không phải là regular. Bạn cần phải lưu trữ trạng thái ở đâu đó (bao nhiêu ký hiệu trước khi \b\b nó đã đọc), nhưng DFA không thể làm điều đó (vì DFA không thể biết số thứ tự có thể tìm thấy). Tất cả các giải pháp được đề xuất chỉ là regexes cho trường hợp của bạn ("\bHellow\b world!!!\b\b\b.") và có thể dễ dàng bị hỏng với thử nghiệm phức tạp hơn.

giải pháp dễ nhất cho trường hợp của bạn được thay thế trong cặp chu kỳ {tất cả ngoại trừ \ b} {\ b}

UPD: Solution, bởi @Bohemian đề xuất dường như hoàn toàn chính xác:

UPD 2: Có vẻ như regexes của java có thể phân tích cú pháp not only regular languages, nhưng cũng có các đầu vào như {a}^n{b}^n với lookahead đệ quy, vì vậy trong trường hợp java có thể khớp các nhóm đó với regex đơn. Cảm ơn bạn đã nhận xét @Pshemo và chỉnh sửa @Elist!

+1

Tôi nghi ngờ rằng điều này có thể được thực hiện với regex, nhưng regex này sẽ rất khó đọc vì vậy nó sẽ là tốt hơn để tạo trình phân tích cú pháp của riêng chúng tôi. – Pshemo

+0

Tôi đang tham khảo lại ví dụ C# được đề cập trong chỉnh sửa của tôi: http://stackoverflow.com/a/16604714/1609201. Có một tương tự trong Java? Nếu không, sự khác biệt trong tính năng Regex giữa hai ngôn ngữ là gì? – Elist

+0

Bây giờ ngay cả với regex Java này: https://stackoverflow.com/questions/3644266/how-can-we-match-an-bn-with-java-regex đó là về một^n b^n? – Pshemo

4

Điều này trông giống như một công việc cho Stack!

Stack<Character> stack = new Stack<Character>(); 

// for-each character in the string 
for (int i = 0; i < str.length(); i++) { 
    char c = str.charAt(i); 

    // push if it's not a backspace 
    if (c != '\b') { 
     stack.push(c); 
    // else pop if possible 
    } else if (!stack.empty()) { 
     stack.pop(); 
    } 
} 

// convert stack to string 
StringBuilder builder = new StringBuilder(stack.size()); 

for (Character c : stack) { 
    builder.append(c); 
} 

// print it 
System.out.println(builder.toString()); 

Regex, trong khi tốt, không phù hợp với mọi công việc. Cách tiếp cận này không ngắn gọn như Bohemian's, nhưng nó hiệu quả hơn. Sử dụng một ngăn xếp là O (n) trong mọi trường hợp, trong khi một cách tiếp cận regex như của Bohemian là O (n) trong trường hợp xấu nhất.

+1

Rõ ràng, ngăn xếp là giải pháp cuối cùng ở đây, nhưng tôi đã tìm kiếm một cách nhanh chóng và 'nội tuyến' để giải quyết vấn đề này. Ngoài ra tôi đã học được một vài thủ thuật regex hay ... – Elist

+1

@Luke và Elist, tôi thích giải pháp này, nhưng khi chỉ "làm mọi thứ", thật tuyệt vời bạn có thể làm gì với regex trong hầu như không có mã - đó là một kỹ năng đáng học . Và nó cũng thực hiện OK - chắc chắn không phải nano giây nhanh, nhưng một cuộc gọi thông thường tới 'replaceAll()' sẽ chỉ mất vài micro giây; đó là "đủ nhanh" và bạn có thể nhanh chóng tiếp tục với phần còn lại của mã và truy cập lại sau nếu bạn cần tăng hiệu suất của ứng dụng. – Bohemian

Các vấn đề liên quan