Chuỗi thay thế Ruby bằng mẫu regex đã được chụp


121

Tôi đang gặp sự cố khi dịch cái này sang Ruby.

Đây là một đoạn JavaScript thực hiện chính xác những gì tôi muốn làm:

function get_code(str){
    return str.replace(/^(Z_.*): .*/,"$1")​​​​​​​​​​​​​​​​​​​​​​​​​​​;
}

Tôi đã thử gsub , subthay thế nhưng dường như không có gì làm được những gì tôi mong đợi.

Dưới đây là ví dụ về những điều tôi đã thử:

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/) { |capture| capture }
"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "$1")
"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "#{$1}")
"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "\1")
"Z_sdsd: sdsd".gsub(/(.).*/) { |capture| capture }

Bạn nên hiển thị mã thực tế cho những gì bạn đã thử.
Amber

@Amber tôi đặt mẫu tôi đã thử.
JD Isaacks

Câu trả lời:


192

Hãy thử '\1'thay thế (các dấu ngoặc kép rất quan trọng, nếu không bạn cần phải thoát khỏi \):

"foo".gsub(/(o+)/, '\1\1\1')
#=> "foooooo"

Nhưng vì bạn dường như chỉ quan tâm đến nhóm nắm bắt, hãy lưu ý rằng bạn có thể lập chỉ mục một chuỗi với regex:

"foo"[/oo/]
#=> "oo"
"Z_123: foobar"[/^Z_.*(?=:)/]
#=> "Z_123"

68
Lưu ý rằng điều này chỉ hoạt động nếu chuỗi thay thế nằm trong dấu nháy đơn . Tôi đã lãng phí 5 phút để tìm ra điều đó.
Vicky Chijwani

7
@MarkThomas - thường thì chúng tôi thử câu trả lời hàng đầu / được chấp nhận đầu tiên mà không đọc toàn bộ câu trả lời. Đó dường như là phương tiện hiệu quả nhất để khắc phục sự cố. Cho Vicky nghỉ ngơi! :)
Josh M.

@VickyChijwani Nhận xét tốt, nhưng cũng lưu ý rằng khi sử dụng Ruby inline (trên dòng lệnh với -e), có nhiều khả năng thấy dấu ngoặc kép : printf "Punkinhead the name" | ruby -ne 'puts gsub /.*(the name)/, "Jonathans \\1"'vì biểu thức được cung cấp -ethường được bao bọc trong dấu ngoặc kép.
Jonathan Komar,

Làm cách nào để thực hiện điều này cho tất cả các lần xuất hiện của mẫu trong chuỗi?
Jagdeep Singh

1
@JagdeepSingh, theo mặc định, nó thay thế tất cả các lần xuất hiện.
Iulian Onofrei

36

\1trong dấu ngoặc kép cần phải được thoát. Vì vậy, bạn muốn một trong hai

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "\\1")

hoặc là

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, '\1')

xem tài liệu trên gsub có nội dung "Nếu đó là một chuỗi được trích dẫn kép, cả hai tham chiếu ngược phải được đặt trước bởi một dấu gạch chéo ngược bổ sung."

Điều đó đang được nói, nếu bạn chỉ muốn kết quả của trận đấu, bạn có thể làm:

"Z_sdsd: sdsd".scan(/^Z_.*(?=:)/)

hoặc là

"Z_sdsd: sdsd"[/^Z_.*(?=:)/]

Lưu ý rằng đây (?=:)là nhóm không chụp để nhóm :không hiển thị trong trận đấu của bạn.



5

Nếu bạn cần sử dụng regex để lọc một số kết quả và SAU ĐÓ chỉ sử dụng nhóm chụp, bạn có thể làm như sau:

str = "Leesburg, Virginia  20176"
state_regex = Regexp.new(/,\s*([A-Za-z]{2,})\s*\d{5,}/)
# looks for the comma, possible whitespace, captures alpha,
# looks for possible whitespace, looks for zip

> str[state_regex]
=> ", Virginia  20176"

> str[state_regex, 1] # use the capture group
=> "Virginia"

2
def get_code(str)
  str.sub(/^(Z_.*): .*/, '\1')
end
get_code('Z_foo: bar!') # => "Z_foo"

0

$ các biến chỉ được đặt để khớp với khối:

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/) { "#{ $1.strip }" }

Đây cũng là cách duy nhất để gọi một phương thức trên trận đấu. Điều này sẽ không thay đổi kết quả phù hợp, chỉ strip"\ 1" (giữ nguyên):

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "\\1".strip)
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.