Ruby sostituisce la stringa con il pattern regex catturato


121

Ho problemi a tradurre questo in Ruby.

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

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

Ho provato gsub , sub e sostituisci 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 }

Dovresti mostrare il codice effettivo per ciò che hai provato.
Amber

@Amber ho messo un campione che ho provato.
JD Isaacks

Risposte:


192

Prova '\1'la sostituzione (le virgolette singole sono importanti, altrimenti devi sfuggire al \):

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

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

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

68
Nota che funziona solo se la stringa di sostituzione è racchiusa tra virgolette singole . Ho perso 5 minuti per capirlo.
Vicky Chijwani

7
@MarkThomas - spesso proviamo prima la risposta migliore / accettata senza leggere la totalità delle risposte. Questo sembra generalmente essere il mezzo più efficiente per risolvere un problema. Dai una pausa a Vicky! :)
Josh M.

@VickyChijwani Buon commento, ma nota anche che quando si utilizza Ruby inline (sulla riga di comando con -e), è più probabile che vengano visualizzati doppi apici : printf "Punkinhead the name" | ruby -ne 'puts gsub /.*(the name)/, "Jonathans \\1"'perché l'espressione fornita a -eè solitamente racchiusa tra virgolette singole.
Jonathan Komar

Come eseguire questa operazione per tutte le occorrenze di pattern nella stringa?
Jagdeep Singh

1
@JagdeepSingh, per impostazione predefinita, sostituisce tutte le occorrenze.
Iulian Onofrei

36

\1tra virgolette doppie deve essere preceduto da caratteri di escape. Quindi vuoi entrambi

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

o

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

vedere la documentazione su gsub dove si dice "Se è una stringa tra virgolette doppie, entrambi i riferimenti all'indietro devono essere preceduti da una barra rovesciata aggiuntiva."

Detto questo, se vuoi solo il risultato della partita puoi fare:

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

o

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

Nota che (?=:)è un gruppo che non cattura, quindi :non compare nella tua corrispondenza.



5

Se è necessario utilizzare un'espressione regolare per filtrare alcuni risultati e POI utilizzare solo il gruppo di acquisizione, è possibile eseguire 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"

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

0

$ le variabili sono impostate solo per corrispondere nel blocco:

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

Questo è anche l'unico modo per chiamare un metodo sulla partita. Questo non cambierà la corrispondenza, solo strip"\ 1" (lasciandolo invariato):

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "\\1".strip)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.