Vim Tip: Replace Numbers with Alphabetic Characters

TL;DR: Replace s_0 with s_1, s_1 with s_2 and so on (assuming the largest number to replace is less than 26):

s/s_\(\d\+\)/\='s_'.(nr2char(97+submatch(1)))/g

Why did I need this?

I had several pages of notes which included TikZ diagrams of finite automata each using node labels of the form s0,s1,sns_0, s_1, \ldots s_n. For example:

\begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto]
  \node[state, initial] (s_0) {$s_0$};
  \node[state, right of=s_0] (s_1) {$s_1$};
  \node[state, accepting, right of=s_1] (s_2) {$s_2$};
	\draw (s_0) edge node {1} (s_1);
	\draw (s_1) edge node {0} (s_2);
\end{tikzpicture}

Whilst reviewing the notes, I realised that it would make more sense for the nodes to be labelled sa,sb,szs_a,s_b,\ldots s_z1 to more clearly show how each diagram contained the nodes from prior diagrams. The node numbers were all less than 26 and so a natural mapping to each letter of the alphabet using ASCII character codes emerges. The lowercase characters start from ASCII code 97 and the uppercase characters start from ASCII code 65.

Lowercase:

a = 97
b = 98
...
z = 122

Uppercase:

A = 65
B = 66
...
Z = 90

Converting from some n{0,1,,25}n \in \{0, 1, \ldots, 25\} to one of these ranges can be done by addition of nn to the first ASCII code in the desired range (97 and 65 for lowercase and uppercase respectively). For the lowercase conversion:

0 -> 97 + 0 = 97 = a
1 -> 97 + 1 = 98 = b
...
25 -> 97 + 25 = 122 = z

The Vim function nr2char returns the character that the given ASCII value represents2. The command in the TL;DR section finds all patterns sns_n where nn is a number, extracts nn, performs the addition described above and passes the result to nr2char to retrieve the corresponding character. Finally, this character is substituted in place of nn in the original text.


  1. Thankfully, none large enough to reach all the way to szs_z↩︎

  2. https://renenyffenegger.ch/notes/development/vim/script/vimscript/functions/nr2char ↩︎


Feedback

Contact me at ben@steadbytes.com or via Twitter @SteadBytes for feedback, questions, etc.