Ruby ersetzt Zeichenfolge durch erfasstes Regex-Muster

120

Ich habe Probleme, dies in Ruby zu übersetzen.

Hier ist ein Stück JavaScript, das genau das tut, was ich tun möchte:

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

Ich habe gsub , sub und replace ausprobiert , aber keiner scheint das zu tun, was ich erwarte.

Hier sind Beispiele für Dinge, die ich versucht habe:

"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
quelle
Sie sollten den tatsächlichen Code für das anzeigen, was Sie versucht haben.
Amber
@ Amber Ich habe Probe gelegt, die ich versucht habe.
JD Isaacks

Antworten:

191

Versuchen Sie es '\1'mit dem Ersatz ( einfache Anführungszeichen sind wichtig, sonst müssen Sie dem entkommen \):

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

Beachten Sie jedoch, dass Sie eine Zeichenfolge mit einem regulären Ausdruck indizieren können, da Sie anscheinend nur an der Erfassungsgruppe interessiert sind:

"foo"[/oo/]
#=> "oo"
"Z_123: foobar"[/^Z_.*(?=:)/]
#=> "Z_123"
Michael Kohl
quelle
68
Beachten Sie, dass dies nur funktioniert, wenn sich die Ersatzzeichenfolge in einfachen Anführungszeichen befindet . Ich habe 5 Minuten damit verbracht, das herauszufinden.
Vicky Chijwani
7
@MarkThomas - oft versuchen wir zuerst die beste / akzeptierte Antwort, ohne die Gesamtheit der Antworten zu lesen. Dies scheint im Allgemeinen das effizienteste Mittel zur Behebung eines Problems zu sein. Gib Vicky eine Pause! :)
Josh M.
@ VickyChijwani Guter Kommentar, aber beachten Sie auch, dass bei Verwendung von Ruby inline (in der Befehlszeile mit -e) eher doppelte Anführungszeichen angezeigt werden : printf "Punkinhead the name" | ruby -ne 'puts gsub /.*(the name)/, "Jonathans \\1"'weil Ausdruck für bereitgestellt wird-e wird normalerweise in einfache Anführungszeichen gesetzt.
Jonathan Komar
Wie geht das für alle Mustervorkommen in der Zeichenfolge?
Jagdeep Singh
1
@JagdeepSingh, Es ersetzt standardmäßig alle Vorkommen.
Iulian Onofrei
36

\1in doppelten Anführungszeichen muss maskiert werden. Also willst du auch nicht

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

oder

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

siehe die Dokumentation auf gsub , wo es heißt : „Wenn es ein Strings in doppelten Anführungszeichen ist, müssen beide wieder Verweise durch einen zusätzlichen Backslash vorangestellt werden.“

Davon abgesehen, wenn Sie nur das Ergebnis des Spiels wollen, können Sie Folgendes tun:

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

oder

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

Beachten Sie, dass es sich bei der (?=:)Gruppe um eine nicht erfassende Gruppe handelt, sodass die Gruppe :in Ihrem Spiel nicht angezeigt wird.

Mark Thomas
quelle
14
 "foobar".gsub(/(o+)/){|s|s+'ball'}
 #=> "fooballbar"
gaurav.singharoy
quelle
4
Ich wusste nicht, dass ich das kann. Nett!
Vreen
5

Wenn Sie einen Regex verwenden müssen, um einige Ergebnisse zu filtern, und DANN nur die Erfassungsgruppe verwenden, können Sie Folgendes tun:

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

$ Variablen werden nur so eingestellt, dass sie mit dem Block übereinstimmen:

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

Dies ist auch die einzige Möglichkeit, eine Methode für das Match aufzurufen. Dies ändert nichts an der Übereinstimmung, nur strip"\ 1" ( bleibt unverändert):

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