2012-03-27 11 views
80

Ho problemi a tradurre questo in Ruby.Ruby sostituisce stringa con motivo regex catturato

Ecco un pezzo di codice JavaScript che fa esattamente quello che voglio fare:

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

ho cercato gsub, sub, e replace ma nessuno sembra fare quello che mi aspetto.

Ecco alcuni esempi di cose che ho provato:

"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 } 
+0

si dovrebbe mostrare il codice vero e proprio per quello che hai provato. – Amber

+0

@Amber Ho inserito un campione che ho provato. –

risposta

138

Prova '\1' per la sostituzione (apici sono importanti, altrimenti è necessario sfuggire alla \):

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

Ma poiché sembra che tu sia interessato solo al gruppo di cattura, tieni presente che puoi indicizzare una stringa con un'espressione regolare:

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

Si noti che questo funziona solo se la stringa di sostituzione si trova all'interno di ** virgolette singole **. Ho perso 5 minuti per capirlo. –

+7

@MarkThomas: spesso proviamo prima la risposta in alto/accettata senza leggere la totalità delle risposte. Questo sembra essere generalmente il mezzo più efficace per risolvere un problema. Dai una pausa a Vicky! :) –

+0

@VickyChijwani Buon commento, ma anche notare che quando si usa Ruby in linea (sulla riga di comando con '-e'), è più probabile che veda ** virgolette **:' printf "Punkinhead il nome" | ruby -ne 'mette gsub /.*(il nome) /, "Jonathans \\ 1"' 'perché l'espressione fornita a' -e' è solitamente racchiusa tra virgolette singole. –

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

\1 tra virgolette deve essere sfuggito. Così si vuole sia

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

o

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

vedere the docs on gsub cui si dice "Se si tratta di una stringa con virgolette doppie, sia back-riferimenti deve essere preceduto da una barra rovesciata aggiuntiva."

Detto questo, se si desidera solo il risultato della partita si può fare:

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

o

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

Si noti che il (?=:) è un gruppo non-cattura in modo che il : non compare nella tua partita.

8
"foobar".gsub(/(o+)/){|s|s+'ball'} 
#=> "fooballbar" 
+2

non sapevo di poterlo fare. Bello! – vreen

1

Se è necessario utilizzare una regex per filtrare alcuni risultati, e quindi utilizzare solo il gruppo di cattura, è possibile effettuare le seguenti operazioni:

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"