2008-11-13 17 views
46

Bei Verwendung regulärer Ausdrücke in Ruby, was ist der Unterschied zwischen $ 1 und \ 1?

Antwort

78

\ 1 ist ein Rückreferenzierung, die nur in der gleichen sub oder gsub Methodenaufruf, zB funktioniert:

"foobar".sub(/foo(.*)/, '\1\1') # => "barbar" 

$ 1 ist eine globale Variable, die in späteren Code verwendet werden können:

if "foobar" =~ /foo(.*)/ then 
    puts "The matching word was #{$1}" 
end 

Ausgang:

"The matching word was bar" 
# => nil 
+0

Beachten Sie, dass [Rubys Behandlung von einfachen und doppelten Anführungszeichen] (http://stackoverflow.com/a/3028799/303896) Ihnen beim Versuch, Rückreferenzen zu verwenden, in die Quere kommen kann. – alxndr

+0

habe nicht viel verstanden, kann jemand bitte etwas mehr Erklärung liefern – YasirAzgar

+0

@ YasirAzgar '.sub()' ist ein Methodenaufruf. '\ 1'' kann (scheinbar) nur im Rahmen eines Aufrufs 'sub' oder' gsub' verwendet werden. Im ersten Beispiel liegt "foobar" .sub (/ foo (. *) /, '\ 1 \ 1') ',' '\ 1'' im Bereich der 'sub'-Methode. Im zweiten Beispiel wird "$ 1" außerhalb einer "sub"/"gsub" -Methode referenziert. Das Beispiel zeigt, dass es kurz nach einem '= ~ '- Aufruf referenziert wird, aber das ist irrelevant. Anscheinend setzt die Verwendung einer Regex '$ 1', die als globale Variable überall referenziert werden kann. – John

29

Denken Sie daran, es gibt eine dritte Option, die b Schlossform von sub. Manchmal brauchst du es. Angenommen, Sie möchten einen Text durch die Rückseite dieses Textes ersetzen. Sie können nicht mehr als $ 1 Verwenden, weil es nicht schnell genug gebunden ist:

"foobar".sub(/(.*)/, $1.reverse) # WRONG: either uses a PREVIOUS value of $1, 
            # or gives an error if $1 is unbound 

Sie auch nicht \1 verwenden können, weil die sub Methode hat nur eine einfache Text-Substitution von \1 mit dem entsprechenden erfassten Text, gibt es keine Magie hier stattfindet:

"foobar".sub(/(.*)/, '\1'.reverse) # WRONG: returns '1\' 

Also, wenn Sie etwas Besonderes machen wollen, sollten Sie die Blockform sub ($ 1, $ 2, $ `, $‘ usw. verfügbar sein wird) verwenden:

"foobar".sub(/.*/){|m| m.reverse} # => returns 'raboof' 
"foobar".sub(/(...)(...)/){$1.reverse + $2.reverse} # => returns 'oofrab' 
+1

Ihr Beispiel könnte irreführend sein - die Übereinstimmung wird an den Block weitergegeben, nicht an die Matchgroups. Wenn Sie also "foobar" in "foorab" ändern möchten, müssten Sie "str" ​​(/ (foo) (\ w +) /) {$ 1 + $ 2.Reverse} ' – rampion

+1

Siehe ri String # sub : In der Blockform wird die aktuelle Match-Zeichenfolge als Parameter übergeben, und Variablen wie $ 1, $ 2, $ ', $ &, und $ werden entsprechend festgelegt. Der Wert, der vom Block zurückgegeben wird, wird für die Übereinstimmung bei jedem Aufruf ersetzt. – rampion

+0

Richtig, ich werde bearbeiten, um es zu löschen. –

Verwandte Themen