I was doing some puzzle where each English letter is replaced by the one two letters down the alphabet. For example, the word apple
is to be transformed into crrng
, as a
+ 2 → c
, b
+ 2 → d
, etc.
In Python, I was able to implement this transformation using the maketrans()
string method. I wonder: Is it possible to do the same via search and replace in Vim?
1. If the alphabetic characters are arranged sequentially in the target encoding (as is the case for ASCII and some alphabets in UTF-8, like English), one can use the following substitution command:
:%s/./\=nr2char(char2nr(submatch(0))+2)/g
(Before running the command, make sure that the encoding
option
is set accordingly.)
However, this replacement implements a non-circular letter shift. A circular shift can be implemented by two substitutions separately handling lowercase and uppercase letters:
:%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
2. Another way is to translate characters using the tr()
function.
Let us assume that the variable a
contains lowercase characters
of an alphabet arranged in correct order, and the variable a1
hold
the string of characters corresponding to those in a
(below is
an example for English letters).
:let a = 'abcdefghijklmnopqrstuvwxyz'
:let a1 = a[2:] . a[:1]
To avoid typing the whole alphabet by hand, the value of a
can be
produced as follows:
:let a = join(map(range(char2nr('a'), char2nr('z')), 'nr2char(v:val)'), '')
Then, to replace each letter on a line by the letter two positions down the alphabet, one can use the following substitution:
:%s/.*/\=tr(submatch(0), a . toupper(a), a1 . toupper(a1))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With