2009-04-19 7 views

risposta

32

La seconda parte di una sostituzione è una stringa doppia citata, pertanto è possibile che si verifichi un'interpolazione normale. Ciò significa che è possibile utilizzare il valore della cattura di indicizzare in un hash:

#!/usr/bin/perl 

use strict; 
use warnings; 


my %replace = (
    quick => "slow", 
    lazy => "energetic", 
); 

my $regex = join "|", keys %replace; 
$regex = qr/$regex/; 

my $s = "The quick brown fox jumps over the lazy dog"; 

$s =~ s/($regex)/$replace{$1}/g; 

print "$s\n"; 
+0

Hai dimenticato il modificatore 'e'. –

+0

Cosa fa? valutare la sostituzione? C'è qualcosa di simile in altri linguaggi di programmazione? – allyourcode

+4

Non ha bisogno/e perché è una semplice interpolazione, prova il codice prima di fare affermazioni. –

8

È possibile effettuare quanto segue.

:%s/quick\(.*\)lazy/slow\1energetic 

Il trucco è quello di utilizzare le parentesi per abbinare il testo tra le due parole. È quindi possibile fare riferimento a questo testo nella stringa di sostituzione utilizzando \1. È inoltre possibile utilizzare \2 per la seconda espressione di paren corrispondente e così via. Ciò consente di sostituire più parole senza disturbare il testo tra di esse.

+2

E se ci sono molte occorrenze di rapida e pigro che sono intercalati? – allyourcode

+1

@allyourcode, quindi sostituirà la coppia più esterna. Questo è solo leggermente differente dall'esempio di Tg che sostituirà il primo occurance. – JaredPar

2

in Perl:

s/quick(.*)lazy/slow${1}energetic/; 

In vim:

s/quick\(.*\)lazy/slow\1energetic/; 
-2

C'è un modo pulito per farlo in Ruby utilizzando gsub con un blocco:

s = "The quick brown fox jumps over the lazy dog" 
subs = {'quick' => 'slow', 'lazy' => 'industrious'} 
s.gsub(/quick|lazy/) { |match| subs[match] } 
# => "The slow brown fox jumps over the industrious dog" 
49

È possibile farlo in vim utilizzando un dizionario:

:%s/quick\|lazy/\={'quick':'slow','lazy':'energetic'}[submatch(0)]/g 

Questo cambierà il seguente testo:

Il rapido marrone volpe correva rapido mente accanto alla pigro ruscello.

in:

Il lento marrone volpe correva lento mente accanto alla energico ruscello.

Per vedere come funziona, vedere :help sub-replace-expression e :help Dictionary. In breve,

  • \= consente di sostituire il risultato di un'espressione vim.
  • {'quick':'slow', 'lazy':'energetic'} è un dizionario Vim (come un hash in perl o rubino o un oggetto in javascript) che utilizza [] per le ricerche.
  • submatch(0) è la stringa corrispondente

Questo può tornare utile durante il refactoring del codice - dicono di voler modificare i nomi delle variabili per foo, bar, e baz cambiando

  • foobar
  • barbaz
  • bazfoo

Utilizzando una sequenza di comandi %s/// sarebbe difficile, a meno che non utilizzato nomi di variabili temporanee - ma che avrebbe dovuto assicurarsi che coloro che non stavano colpendo qualsiasi altra cosa. Invece, è possibile utilizzare un dizionario per farlo in un solo passaggio:

:%s/\<\%(foo\|bar\|baz\)\>/\={'foo':'bar','bar':'baz','baz':'foo'}[submatch(0)]/g 

che cambia questo codice

int foo = 0; 
float bar = pow(2.0, (float) foo); 
char baz[256] = {}; 

sprintf(baz,"2^%d = %f\n", foo, bar); 

in:

int bar = 0; 
float baz = pow(2.0, (float) bar); 
char foo[256] = {}; 

sprintf(foo,"2^%d = %f\n", bar, baz); 

Se vi trovate a fare questo molto, potresti aggiungere quanto segue al tuo ~/.vimrc:

" Refactor the given lines using a dictionary 
" replacing all occurences of each key in the dictionary with its value 
function! Refactor(dict) range 
    execute a:firstline . ',' . a:lastline . 's/\C\<\%(' . join(keys(a:dict),'\|'). '\)\>/\='.string(a:dict).'[submatch(0)]/ge' 
endfunction 

command! -range=% -nargs=1 Refactor :<line1>,<line2>call Refactor(<args>) 

Questa opzione consente di utilizzare il comando :Refactor {'frog':'duck', 'duck':'frog'} ed è leggermente meno ripetitivo di rispetto alla creazione manuale di regex per il dict. risposta

0

Chas è buona, l'unica altra cosa che vorrei menzionare è che se si sta facendo di parola swap probabilmente si desidera essere corrispondenti a

\ b (foo | bar | baz | qux) \ b

per evitare sottostringhe corrispondenti. Se si fa un sacco di parola scambio, si potrebbe iniziare a trovare espressioni regolari un po 'limitanti e voglia di fare qualcosa di simile:

join '', map { exists $subst{$_} ? $subst{$_} : $_ } split /\b/, $string 
14

È possibile concatenare sostituzioni Vim:

Il quick brown fox corse velocemente vicino al ruscello pigro.

:s/quick/slow/|s/lazy/energetic/ 

La lenta volpe marrone correva rapidamente accanto al ruscello energico.

Il vantaggio è che si deve digitare le vostre sostituzioni solo una volta

Rgds

+1

Non una singola espressione regolare come richiesto dalla domanda, ma +1 per la migliore soluzione alla parte vim del problema, IMHO. Grazie! –

Problemi correlati