2013-08-06 32 views
23

Tôi có văn bản như:Làm cách nào để giữ các dấu phân cách khi tách chuỗi Ruby?

content = "Do you like to code? How I love to code! I'm always coding." 

Tôi đang cố gắng để tách nó trên hoặc là một ? hoặc . hoặc !:

content.split(/[?.!]/) 

Khi tôi in ra kết quả, delimiters chấm câu bị thiếu.

Bạn có muốn mã

Làm thế nào tôi yêu mã

Tôi luôn mã hóa

Làm thế nào tôi có thể giữ dấu chấm câu?

+0

Vì vậy, về cơ bản bạn muốn đặt dòng mới sau mỗi dấu phân cách? Giá trị thực tế bạn muốn được trả lại (trong mã Ruby) là gì? – Agis

+0

Tôi không chắc ý nghĩa của việc đó (tức là đặt một dòng mới sau mỗi dấu phân tách) là cách tôi sẽ trình bày dữ liệu. Vì 'split' trả về kết quả trong một mảng, tôi muốn dấu chấm câu được bao gồm với mỗi câu trong phần tử của mảng sao cho khi tôi in các phần tử của mảng một cách riêng biệt, chúng có ý nghĩa với dấu chấm câu. – BrainLikeADullPencil

Trả lời

26

trả lời

Sử dụng một biểu hiện tích cực lookbehind thường xuyên (ví dụ ?<=) bên trong một nhóm chụp ngoặc để giữ delimiter vào cuối mỗi chuỗi:

content.split(/(?<=[?.!])/) 

# Returns an array with: 
# ["Do you like to code?", " How I love to code!", " I'm always coding."] 

Điều này khiến một khoảng trắng ở đầu chuỗi thứ hai và thứ ba. Thêm một trận đấu cho zero hoặc nhiều không gian trắng (\s*) sau khi nhóm chụp để loại trừ nó:

content.split(/(?<=[?.!])\s*/) 

# Returns an array with: 
# ["Do you like to code?", "How I love to code!", "I'm always coding."] 

Ghi chú bổ sung

Trong khi nó không có ý nghĩa với ví dụ của bạn, dấu phân cách có thể được chuyển sang phía trước của chuỗi bắt đầu bằng chuỗi thứ hai. Điều này được thực hiện với biểu thức chính quy nhìn chung tích cực (ví dụ: ?=). Vì lợi ích của bất cứ ai tìm kiếm kỹ thuật đó, dưới đây là cách để làm điều đó:

content.split(/(?=[?.!])/) 

# Returns an array with: 
# ["Do you like to code", "? How I love to code", "! I'm always coding", "."] 

Một ví dụ tốt để minh họa cho hành vi này là:

content = "- the - quick brown - fox jumps" 
content.split(/(?=-)/) 

# Returns an array with: 
# ["- the ", "- quick brown ", "- fox jumps"] 

ý rằng nhóm chụp khung vuông là không cần thiết vì chỉ có một dấu phân tách. Ngoài ra, kể từ khi trận đấu đầu tiên xảy ra ở ký tự đầu tiên nó kết thúc như là mục đầu tiên trong mảng.

+1

Cảm ơn nó hoạt động nhưng bạn có thể giải thích? – BrainLikeADullPencil

+1

@BrainLikeADullPencil kiểm tra [liên kết này] (http://www.regular-expressions.info/lookaround.html) – fotanus

+0

Hoặc là '@ content.split (/ (? = \? | \. |!) /)', theo đó phần nào bạn muốn đánh dấu là – fotanus

2

Cách tốt nhất để làm điều này là với một thư viện xử lý ngôn ngữ tự nhiên: Rails gem to break a paragraph into series of sentences

Bạn cũng có thể chia nhỏ thành từng nhóm:

@content.split(/(\?+)|(\.+)|(!+)/) 

Sau khi chia tách thành các nhóm, bạn có thể tham gia các câu và dấu phân cách .

@content.split(/(\?+)|(\.+)|(!+)/).each_slice(2) {|slice| puts slice.join} 
6

Tôi muốn sử dụng cái gì đó như:

content.scan(/.+?[?!.]/) 
# => ["Do you like to code?", " How I love to code!", " I'm always coding."] 

Nếu bạn muốn thoát khỏi không gian can thiệp, sử dụng:

content.scan(/.+?[?!.]/).map(&:lstrip) 
# => ["Do you like to code?", "How I love to code!", "I'm always coding."] 
10

Để trả lời câu tiêu đề của câu hỏi, thêm một nhóm chụp để bạn split regex sẽ giữ lại các dấu tách phân tách:

"Do you like to code? How I love to code! I'm always coding.".split /([?!.])/ 
    => ["Do you like to code", "?", " How I love to code", "!", " I'm always coding", "."] 

Từ đó, nó khá đơn giản để lại xây dựng các câu (hoặc làm việc xoa bóp khác như vấn đề gọi cho nó):

Các regex được đưa ra trong các câu trả lời khác hoàn thành phần thân câu hỏi ngắn gọn hơn.

6

Sử dụng partition. Ví dụ từ tài liệu:

"hello".partition("l")   #=> ["he", "l", "lo"] 
+1

Điều này chỉ hoạt động nếu có một trường hợp riêng lẻ của dấu tách hoặc bạn chỉ quan tâm đến trường hợp đầu tiên. Mỗi tài liệu Ruby trên 'phân vùng':" Tìm kiếm sep hoặc mẫu (regexp) trong chuỗi và trả về phần trước đó, khớp, và phần sau nó. Nếu không tìm thấy, trả về hai chuỗi rỗng và str. " Vì vậy, ''hellollo'.partition (' l ')' trở thành '[" anh "," l "," lollo "]'. Sử dụng giải pháp của Chris Heald nếu bạn muốn tất cả chúng: ''hellollo'.split (/ (l) /) # => [" anh "," l "," "," l "," o "," l " , "", "l", "o"] ' –

+0

@ Chrisbloom7 điểm tốt, tôi không biết điều đó! – Bob

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