2011-10-03 32 views
6

Tôi đoán đây sẽ là một sai lầm ngớ ngẩn nhưng đối với tôi, sau đây trả về một mảng chỉ chứa "M". Xem phần này:Ruby Regex, Chỉ một lần chụp (Rất đơn giản!)

/(.)+?/.match("Many many characters!").captures 
=> ["M"] 

Tại sao nó không trả về một mảng của mỗi ký tự? Tôi chắc hẳn đã bỏ lỡ điều gì đó rõ ràng bởi vì tôi không thể thấy điều gì sai trái với điều này?

Chỉnh sửa: Chỉ cần nhận ra, tôi không cần dấu +? nhưng nó vẫn không hoạt động nếu không có nó.

Chỉnh sửa: Xin lỗi! Tôi sẽ làm rõ: mục tiêu của tôi là cho phép người dùng nhập biểu thức và kiểu dáng thông thường và tệp văn bản đầu vào, bất cứ nơi nào có khớp, văn bản sẽ được bao quanh với phần tử html và kiểu dáng sẽ được áp dụng, tôi không chỉ tách chuỗi ký tự, tôi chỉ sử dụng regex đã cho bởi vì nó là đơn giản nhất mặc dù đó là ngu ngốc trên một phần của tôi. Làm thế nào để tôi có được nhóm chụp từ quét() hoặc là không thể? Tôi thấy rằng $ 1 chứa "!" (trận đấu cuối cùng?) và không phải bất kỳ người nào khác.

Chỉnh sửa: Gosh, nó thực sự không phải là ngày của tôi. Như injekt đã thông báo cho tôi, các ảnh chụp được lưu trữ trong các mảng riêng biệt. Làm thế nào để tôi có được bù đắp của những ảnh chụp từ chuỗi gốc? Tôi muốn có thể có được bù đắp của một ảnh chụp sau đó bao quanh nó bằng một chuỗi khác. Hoặc đó là những gì gsub là cho? (Tôi nghĩ rằng chỉ thay thế của trận đấu, không phải là một nhóm chụp)

thức Hy vọng chỉnh sửa: Đúng vậy, hãy để tôi chỉ bắt đầu này một lần nữa: P

Vì vậy, tôi có một chuỗi. Người dùng sẽ sử dụng tệp cấu hình để nhập cụm từ thông dụng, sau đó là kiểu được liên kết với từng nhóm chụp. Tôi cần để có thể quét toàn bộ chuỗi và nhận được sự bắt đầu và kết thúc hoặc bù đắp và kích thước của mỗi trận đấu nhóm.

Vì vậy, nếu người dùng đã cấu hình ([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4}) (địa chỉ email) sau đó tôi sẽ có thể nhận được:

[ ["elliotpotts", 0, 11], 
    ["sample.",  12, 7], 
    ["com",   19, 3] ] 

từ chuỗi: "[email protected]"

Nếu đó không phải là rõ ràng, có điều gì đó sai trái với tôi: P. Cảm ơn rất nhiều cho đến nay guys, và cảm ơn bạn đã kiên nhẫn!

+0

Tôi vừa xem chỉnh sửa, nhóm chụp từ quét được lưu trữ trong các mảng riêng biệt, chỉ cần thử regexp và chuỗi kiểm tra trong irb bạn sẽ thấy. Câu trả lời vẫn giữ nguyên với chỉnh sửa được bao gồm –

+0

Chỉ cần xem chỉnh sửa tiếp theo của bạn, bạn sẽ phải cập nhật thêm thông tin. Bây giờ tôi hơi bối rối: P Cảm thấy tự do để đưa ra một ví dụ hoàn chỉnh hơn cho dù chúng ta có giả vờ như thế nào để chúng ta biết chính xác những gì bạn cần trích xuất –

+0

Được rồi, đã cập nhật câu trả lời của tôi với bản chỉnh sửa mới nhất của bạn. Tôi là một chút gắn liền với thời gian ngay bây giờ vì vậy nó chỉ là giải pháp hoàn chỉnh không có lời giải thích, cho tôi biết nếu nó không có ý nghĩa và tôi sẽ cập nhật nó –

Trả lời

9

Bởi vì chụp của bạn chỉ phù hợp với một nhân vật duy nhất.(.)+ là không giống như (.+)

>> /(.)+?/.match("Many many characters!").captures 
=> ["M"] 
>> /(.+)?/.match("Many many characters!").captures 
=> ["Many many characters!"] 
>> /(.+?)/.match("Many many characters!").captures 
=> ["M"] 

Nếu bạn muốn kết hợp tất cả các nhân vật một cách đệ quy sử dụng String#scan hoặc String#split nếu bạn không quan tâm đến nhóm chụp

Sử dụng quét:

"Many many characters!".scan(/./) 
#=> ["M", "a", "n", "y", " ", "m", "a", "n", "y", " ", "c", "h", "a", "r", "a", "c", "t", "e", "r", "s", "!"] 

Note rằng câu trả lời khác đang sử dụng (.) trong khi đó là tốt nếu bạn quan tâm đến nhóm chụp, nó là một chút vô nghĩa nếu bạn không, nếu không nó sẽ trả lại MỌI CHARACTER trong đó là ow n mảng riêng biệt, như thế này:

[["M"], ["a"], ["n"], ["y"], [" "], ["m"], ["a"], ["n"], ["y"], [" "], ["c"], ["h"], ["a"], ["r"], ["a"], ["c"], ["t"], ["e"], ["r"], ["s"], ["!"]] 

Nếu không, chỉ cần sử dụng split: "Many many characters!".split(' ')"

EDIT Trong thư trả lời để chỉnh sửa của bạn:

reg = /([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/ 
str = "[email protected]" 
str.scan(reg).flatten.map { |capture| [capture, str.index(capture), capture.size] } 
#=> [["elliotpotts", 0, 11], ["sample.", 12, 7], ["com", 19, 3]]` 

Oh, và bạn không cần phải quét , bạn không thực sự quét nên bạn không cần phải duyệt qua, ít nhất không phải với ví dụ bạn đã cung cấp:

str.match(reg).captures.map { |capture| [capture, str.index(capture), capture.size] } 

Cũng sẽ làm việc

+0

Cảm ơn bạn! Tôi cũng đã tìm thấy một câu trả lời thay thế và sẽ đăng nó ngay bây giờ. Cảm ơn bạn! – Ell

+0

Hai đoạn mã được cung cấp không hoạt động chính xác cho các offset trong trường hợp chung, chúng chỉ hoạt động nếu các phần tử phù hợp khác nhau. Ví dụ: nếu có 3 kết quả phù hợp cho "h" thì chỉ mục tương tự (ví dụ đầu tiên của 'h') được trả về 3 lần. str.index (capture) trả về chỉ mục của thể hiện FIRST của chuỗi con bị bắt. – jpwynn

0

Chỉ trả về một ký tự vì đó là tất cả những gì bạn đã yêu cầu. Bạn có thể muốn sử dụng scan thay vì:

str = "Many many characters!" 
matches = str.scan(/(.)/) 
1

Vâng, một cái gì đó quan trọng đã bỏ lỡ ;-)

(...) chỉ giới thiệu một nhóm thu thập: số lần nhóm phù hợp là không thích hợp như chỉ số được xác định chỉ bởi thường xuyên biểu hiện chính nó và không phải là đầu vào.

Khóa là "biểu thức chính quy toàn cầu", sẽ áp dụng cụm từ thông dụng nhiều lần theo thứ tự. Trong Ruby này được thực hiện với đảo ngược Regex#match-String#scan (nhiều ngôn ngữ khác có một "/ g" modifier biểu thức chính quy):

"Many many chara­cters!".sc­an(/(.)+?/­) 
# but more simply (or see answers using String#split) 
"Many many chara­cters!".sc­an(/(.)/­) 

Chúc mừng mã hóa

0

Các mã sau đây là từ Get index of string scan results in ruby và sửa đổi cho thích của tôi .

[].tap {|results| 
    "abab".scan(/a/) {|capture| 
     results.push(([capture, Regexp::last_match.offset(0)]).flatten) 
    } 
} 

=> [["a", 0], ["a", 2]] 
Các vấn đề liên quan