Ruby mengganti string dengan pola regex yang ditangkap

121

Saya mengalami masalah saat menerjemahkan ini ke dalam Ruby.

Berikut adalah bagian dari JavaScript yang melakukan persis apa yang ingin saya lakukan:

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

Saya telah mencoba gsub , sub , dan mengganti tetapi tampaknya tidak ada yang melakukan apa yang saya harapkan.

Berikut adalah contoh hal yang telah saya coba:

"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 }
JD Isaacks
sumber
Anda harus menunjukkan kode sebenarnya untuk apa yang telah Anda coba.
Amber
@Amber Saya menaruh sampel saya telah mencoba.
JD Isaacks

Jawaban:

192

Coba '\1'penggantinya ( tanda kutip tunggal penting, jika tidak, Anda harus keluar dari \):

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

Tetapi karena Anda sepertinya hanya tertarik pada grup penangkapan, perhatikan bahwa Anda dapat mengindeks string dengan regex:

"foo"[/oo/]
#=> "oo"
"Z_123: foobar"[/^Z_.*(?=:)/]
#=> "Z_123"
Michael Kohl
sumber
68
Perhatikan bahwa ini hanya berfungsi jika string pengganti ada di dalam tanda kutip tunggal . Saya membuang waktu 5 menit untuk memikirkannya.
Vicky Chijwani
7
@MarkThomas - sering kali kami mencoba jawaban teratas / diterima terlebih dahulu tanpa membaca keseluruhan jawaban. Ini tampaknya menjadi cara paling efisien untuk memperbaiki masalah. Beri Vicky istirahat! :)
Josh M.
@VickyChijwani Komentar yang bagus, tetapi perhatikan juga bahwa saat menggunakan Ruby sebaris (pada baris perintah dengan -e), kemungkinan besar akan melihat tanda kutip ganda : printf "Punkinhead the name" | ruby -ne 'puts gsub /.*(the name)/, "Jonathans \\1"'karena ekspresi yang diberikan kepada -ebiasanya dibungkus dalam tanda kutip tunggal.
Jonathan Komar
Bagaimana melakukan ini untuk semua kemunculan pola dalam string?
Jagdeep Singh
1
@JagdeepSingh, Ini, secara default, menggantikan semua kemunculan.
Iulian Onofrei
36

\1dalam tanda kutip ganda harus di-escape. Jadi, Anda juga menginginkannya

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

atau

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

lihat dokumen di gsub di mana dikatakan "Jika ini adalah string kutip ganda, kedua referensi balik harus diawali dengan garis miring terbalik tambahan."

Karena itu, jika Anda hanya menginginkan hasil pertandingan, Anda dapat melakukan:

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

atau

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

Perhatikan bahwa (?=:)adalah grup non-penangkap sehingga :tidak muncul dalam pertandingan Anda.

Mark Thomas
sumber
14
 "foobar".gsub(/(o+)/){|s|s+'ball'}
 #=> "fooballbar"
gaurav.singharoy
sumber
4
tidak tahu saya bisa melakukan itu. Bagus!
vreen
5

Jika Anda perlu menggunakan regex untuk memfilter beberapa hasil, dan KEMUDIAN hanya menggunakan grup pengambilan, Anda dapat melakukan hal berikut:

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"
grumpit
sumber
2
def get_code(str)
  str.sub(/^(Z_.*): .*/, '\1')
end
get_code('Z_foo: bar!') # => "Z_foo"
maerics
sumber
0

$ variabel hanya disetel ke kecocokan ke dalam blok:

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

Ini juga satu-satunya cara untuk memanggil metode pada pertandingan. Ini tidak akan mengubah kecocokan, hanya strip"\ 1" (biarkan tidak berubah):

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