我想用tr
做一些 rot13 转换。我可以很好地理解这个命令:
tr A-Za-z N-ZA-Mn-za-m <<< "URYC ZR CYRNFR"
哪个输出是HELP ME PLEASE
,但我无法弄清楚另一个命令如何产生相同的 rot13 转换:
tr .............A-Z A-ZA-Z <<< "URYC ZR CYRNFR"
所以我有两个问题:
- 第二个命令背后的魔力是什么
tr
? - 如何使第二个命令适用于小写和大写,就像第一个命令一样?
答案1
其工作原理如下:
SET1-> .............ABCDEFGHIJKLMNOPQRSTUVWXYZ
SET2-> ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
所以tr
将翻译SET1
为SET2
.
这相当于第一个,因为它也按13
单位移动,因为有 13 个点。
要包含小写字母,您必须SET1
以类似的偏移量排列它们,即:
.............ABCDEFGHIJKLMNOPQRSTUVWXYZ..........................abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzabcdefghijklm
Z
和之间有 26 个点a
,跨越了一半大写字母和一半小写字母。所以tr
命令本身将是:
tr .............A-Z..........................a-z A-ZA-Za-za-z
答案2
正如 @Prvt_Yadv 在他们的回答中所说,它有效是因为有 13 个点。
集合是
First set: .............ABCDEFGHIJKLMNOPQRSTUVWXYZ
Second set: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
点不是特殊字符,因此如果您的输入中有点,它也会被翻译。在我拥有的版本中tr
,它是第二组中的最后一个对应字符,在本例中是M
:
$ echo URYC ZR CYRNFR. | tr .............A-Z A-ZA-Z
HELP ME PLEASEM
(我可以想象 的不同版本tr
可能会使用集合 2 中的第一个匹配字符,这将给出一个A
。)
回答你的第二个问题,您需要第一组中另外 13 个点来“用完”第二组中剩余的大写字母:
First set: .............ABCDEFGHIJKLMNOPQRSTUVWXYZ.............
Second set: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
然后你可以重复该模式:
First set: .............ABCDEFGHIJKLMNOPQRSTUVWXYZ..........................abcdefghijklmnopqrstuvwxyz
Second set: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
这给了我们:
tr .............A-Z..........................a-z A-ZA-Za-za-z
所以:
$ echo Uryc zr cyrnfr | tr .............A-Z..........................a-z A-ZA-Za-za-z
Help me please
就我个人而言,我认为您问题中的第一种方法更简单!
第一种方法也不转换输入中的任何其他字符。例如,比较:
$ echo Uryc zr cyrnfr. | tr .............A-Z..........................a-z A-ZA-Za-za-z
Help me pleasem
和
$ echo Uryc zr cyrnfr. | tr A-Za-z N-ZA-Mn-za-m
Help me please.
答案3
好的,感谢@Prvt_Yadv,我能够理解这些点。这是第一个问题的答案:
第二个命令背后的魔力是什么
tr
?
这 13 个点只是映射到第二组中的前 13 个字母。所以
tr .............A-Z A-ZA-Z
将产生以下集合:
SET1 -> .............ABCDEFGHIJKLMNOPQRSTUVXWYZ
SET2 -> ABCDEFGHIJKLMNOPQRSTUVXWYZABCDEFGHIJKLMNOPQRSTUVXWYZ
如果您的输入不包含点,您可以丢弃初始序列,因为您不会使用这些替换。那么这些集合将变成:
SET1 -> ABCDEFGHIJKLMNOPQRSTUVXWYZ
SET2 -> NOPQRSTUVXWYZABCDEFGHIJKLMNOPQRSTUVXWYZ
但由于第一组已经包含所有 26 个字母,而第二组有重复的尾随字母,这些也被丢弃,最终变成
SET1 -> ABCDEFGHIJKLMNOPQRSTUVXWYZ
SET2 -> NOPQRSTUVXWYZABCDEFGHIJKLM
这是 rot13 替换,与第一个命令相同(除了这里不处理小写字母)。同样的逻辑可以应用于问题的标题:
tr ...A-Z A-ZA-Z <<< “JVPQBOV”
将产生以下集合:
SET1 -> ...ABCDEFGHIJKLMNOPQRSTUVXWYZ
SET2 -> ABCDEFGHIJKLMNOPQRSTUVXWYZABCDEFGHIJKLMNOPQRSTUVXWYZ
丢弃初始序列和尾随重复字母,它们变成:
SET1 -> ABCDEFGHIJKLMNOPQRSTUVXWYZ
SET2 -> DEFGHIJKLMNOPQRSTUVXWYZABC
这是 rot3 替换。
现在来说第二个问题:
如何使第二个命令适用于小写和大写,就像第一个命令一样?
为了让它发挥作用,你可以在开头放置所需数量的点,将你的 rot 和 26 个点匹配到上部序列和下部序列之间,就像这样:
tr ........A-Z..........................a-z A-ZA-Za-za-z
这将成功创建一个不敏感的 rot8。为了直观地理解为什么这是有效的,让我们看看这些集合:
SET1 -> ........ABCDEFGHIJKLMNOPQRSTUVXWYZ..........................abcdefghijklmnopqrstuvxwyz
SET2 -> ABCDEFGHIJKLMNOPQRSTUVXWYZABCDEFGHIJKLMNOPQRSTUVXWYZabcdefghijklmnopqrstuvxwyzabcdefghijklmnopqrstuvxwyz
排除点映射和尾随字母:
SET1 -> ABCDEFGHIJKLMNOPQRSTUVXWYZabcdefghijklmnopqrstuvxwyz
SET2 -> IJKLMNOPQRSTUVXWYZABCDEFGHijklmnopqrstuvxwyzabcdefgh
现在它适用于大写和小写:)
使其工作的另一种方法是使用tr
如下两个命令:
tr .............A-Z A-ZA-Z <<< "ABJ V hqrefgnaq" | tr .............a-z a-za-z
@iruvar 给出了使用点替换的警告:当输入字符串包含点时,此命令将无法按预期工作。这是因为这些点被映射到其他字母,并且在进行替换时,tr
会将输入点更改为最后一个映射的字母。但实际上您可以使用点以外的任何其他字符。因此,如果在tr
命令中使用点有问题,您可以使用@
例如。这同样可以工作:
tr @@@@@@@@@@@@@A-Z A-ZA-Z <<< "GUNAX LBH NYY..."