2011-10-07 15 views
5

Stavo facendo un puzzle, in cui ogni carattere inglese è sostituito da 2 caratteri avanzati. Ad esempio "apple" verrebbe scritto come "crrng" a + 2 = c, ... e similmente per pple. In python maketrans ho potuto farlo.Ricerca e sostituzione VIM

Mi chiedevo se la cosa simile è possibile nella ricerca VIM & sostituire ??

Qualche idea ???

risposta

9

Se i caratteri alfabetici sono disposte in sequenza in bersaglio codifica , utilizzare il seguente comando cambio .

:%s/./\=nr2char(char2nr(submatch(0))+2)/g 

Tuttavia, questa sostituzione implementa la lettera spostamento non circolare. Uno spostamento circolare può essere implementato con due sostituzioni che gestiscono separatamente le lettere maiuscole e maiuscole.

:%s/\l/\=nr2char(char2nr('a') + (char2nr(submatch(0)) - char2nr('a') + 2) % 26)/g 
:%s/\u/\=nr2char(char2nr('A') + (char2nr(submatch(0)) - char2nr('A') + 2) % 26)/g 

Un altro modo è quello di tradurre i caratteri usando la funzione tr(). Supponiamo che la variabile contenga caratteri minuscoli di un alfabeto disposti nell'ordine corretto e che la variabile contenga la stringa di caratteri corrispondente a quelli in a (di seguito è riportato un esempio di lettere inglesi).

:let a = 'abcdefghijklmnopqrstuvwxyz' 
:let a1 = a[2:] . a[:1] 

per evitare di digitare l'intero alfabeto a mano, il valore di a possono essere prodotti come segue,

:let a = join(map(range(char2nr('a'), char2nr('z')), 'nr2char(v:val)'), '') 

Poi, da sostituire ogni lettera in una linea da una lettera due posizioni lungo la alfabeto, utilizzare la sostituzione

:%s/.*/\=tr(submatch(0), a . toupper(a), a1 . toupper(a1)) 

È vero per ASCII e alcuni alfabeti in UTF-8, ad es. Inglese.

Prima di eseguire il comando, assicurarsi che l'opzione encoding è impostato di conseguenza.

+0

Grazie .. Ma se voglio avere la sostituzione circolare ..come y-> a z-> b è possibile in una sola riga? – hari

+0

@hari: vedere la modifica della risposta. –

+0

solo una piccola osservazione: il '.' che concatena la stringa rende difficile la lettura quando si esegue il codice in C++, preferirei riempirlo con spazi su entrambi i lati (sembra che non l'hai golfato questa volta, dati gli spazi dopo le virgole !) – Benoit

0

Non riesco a pensare a nulla in vim, ma potreste usare l'utilità della riga di comando unix 'tr' (sta per tradurre, credo).

1

Sì, \= eseguirà la funzione

%s/\(.\)/\=nr2char(char2nr(submatch(1)) + 2)/g 
+1

non è necessario utilizzare un gruppo corrispondente, vedere la soluzione di ib. 'submatch (0)' corrisponderà all'intero pattern. – Benoit

0

Il puzzle che descrivi è ampiamente conosciuto come il cifrario di Cesare, ed è normalmente realizzato tramite il comando tr o sed -e y/. Dato che y non è disponibile in vim, avrai bisogno di un trucco piuttosto sporco come ib proposto, ma chiamare tr è un lavoro molto più bello.

Soprattutto considerando il caso d'angolo di y e z: presumo che questi debbano essere mappati rispettivamente su aeb e b?

Problemi correlati