如何在 Vim 中实现类似凯撒密码的文本替换?

发布于 2024-12-09 03:48:47 字数 288 浏览 0 评论 0原文

我正在做一些拼图,其中每个英文字母都被字母表中的两个字母取代。例如,单词 apple 将转换为 crrng,如 a + 2 → cb + 2 → d 等。

在 Python 中,我能够使用以下方法实现此转换maketrans() 字符串方法。我想知道:是否可以通过 Vim 中的搜索和替换来执行相同的操作?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

耶耶耶 2024-12-16 03:48:47

1.如果目标中字母字符按顺序排列
编码(如 ASCII 和 UTF-8 中的某些字母表的情况,例如
英文),可以使用以下替换命令:(

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

运行该命令之前,请确保 encoding 选项
进行相应设置。)

但是,此替换实现了非循环字母移位。
循环移位可以分别通过两次替换来实现
处理小写和大写字母:

:%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. 另一种方法是使用 tr() 函数翻译字符。
让我们假设变量 a 包含小写字符
按正确顺序排列的字母表,并且变量 a1 保持
对应于 a 中的字符串(下面是
英文字母的示例)。

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

为了避免手动输入整个字母表,a 的值可以是
生成如下:

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

然后,将一行中的每个字母替换为向下两位字母
字母表中,可以使用以下替换:

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

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))
泅渡 2024-12-16 03:48:47

是的,\=将执行该函数

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

Yes, \= will execute the function

%s/\(.\)/\=nr2char(char2nr(submatch(1)) + 2)/g
忘东忘西忘不掉你 2024-12-16 03:48:47

想不出 vim 中的任何内容,但您可以使用 unix 命令行实用程序“tr”(我相信代表翻译)。

Can't think of anything in vim, but you could use the unix command line utility 'tr' (stands for translate, I believe).

等数载,海棠开 2024-12-16 03:48:47

您描述的难题被广泛称为凯撒密码,通常通过 tr 命令或 sed -ey/ 实现。由于 y 在 vi​​m 中不可用,因此您需要像 ib 建议的那样进行相当肮脏的黑客攻击,但调用 tr 是更好的工作。

特别是考虑 y 和 z 的极端情况:我假设它们应该分别映射到 a 和 b?

The puzzle you describe is widely known as the caesar cipher, and is normally implemented via the tr command or sed -e y/. Since y is not available in vim, you'll need a pretty dirty hack like ib proposed, but calling tr is much nicer work.

Especially considering the corner case of y and z: I assume these should be mapped to a and b, respectively?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文