【发布时间】:2011-09-20 10:33:54
【问题描述】:
如何在不使用硬编码字典的情况下,在 bash 中将字符串的每个字母向下或向上移动给定数量的字母?
【问题讨论】:
如何在不使用硬编码字典的情况下,在 bash 中将字符串的每个字母向下或向上移动给定数量的字母?
【问题讨论】:
$ alpha=abcdefghijklmnopqrstuvwxyz
$ rot=3
$ sed "y/${alpha}/${alpha:$rot}${alpha::$rot}/" <<< 'foobar'
irredu
【讨论】:
你的意思是像ROT13这样的吗:
pax$ echo 'hello there' | tr '[a-z]' '[n-za-m]'
uryyb gurer
pax$ echo 'hello there' | tr '[a-z]' '[n-za-m]' | tr '[a-z]' '[n-za-m]'
hello there
对于想要提供任意旋转(0 到 26)的更通用的解决方案,您可以使用:
#!/usr/bin/bash
dual=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
phrase='hello there'
rotat=13
newphrase=$(echo $phrase | tr "${dual:0:26}" "${dual:${rotat}:26}")
echo ${newphrase}
【讨论】:
/usr/bin 或 /usr/games 中可能有一个 rot13 工具,这将是另一种方法。
如果你也想旋转大写字母,你可以使用这样的东西:
cat data.txt | tr '[a-z]' '[n-za-m]' | tr '[A-Z]' '[N-ZA-M]'
data.txt 包含您想要旋转的任何内容。
【讨论】:
或者
cat data.txt | tr 'a-zA-Z' 'n-za-mN-ZA-M'
它也可以工作
【讨论】:
Shift by 12 characters(A becomes M, and vice versa)
Encryption
----------
$> echo ABCDE | tr '[A-Z]' '[M-ZA-L]' // prints MNOPQ
Decryption
----------
$> echo MNOPQ | tr '[M-ZA-L]' '[A-Z]' // prints ABCDE
在加密示例中,我们将 ABCDE 传递给命令tr,该命令有两个参数。第一个是匹配的字符串。它将匹配您输入中的某些字符串(在我们的例子中为 ABCDE)。第二个参数作用于第一个参数的结果并相应地修改它。因此,我们基本上匹配输入 ABCDE 中存在的任何大写字母并将其传递给第二个参数。第二个参数将字符替换为下一个对应的第 12 个字符。现在,这部分理解起来很重要,可能会让一些人感到困惑,我们基本上是从第二个参数中的[M-L] 开始的。由于tr 命令不直接接受这个,我们将它分成两个单独的块。第一个块是[M-Z],第二个块是[A-L]。它基本上就像一个搜索和替换机制。你用第一个参数搜索,用第二个参数修改,就这么简单。
对于第二个示例,我刚刚在tr 命令中将第一个参数与第二个参数进行了交换。它完美地充当解密器。你可以像第一个例子一样写它,但是我发现当我有加密算法时它更省时,我也可以交换参数来有一个解密算法。
【讨论】:
不使用 tr,移动 1 到 25 个字符 并且可以使用26-原始密钥解密
#!/bin/bash
#set -x
i=0
for letters in {A..Z}
do
abc_cap[$i]="$letters"
((i++))
done
i=0
for letters in {a..z}
do
abc_small[$i]="$letters"
((i++))
done
read -r -p "Enter message to be encrypted/decrypted: " -a message
read -r -p "Enter shift amount (26 - orig key for decrypt): " shift_amount
echo -n "Encrypted message: "
if [ "$shift_amount" -gt 25 ] || [ "$shift_amount" -lt 1 ]
then
echo "Shift amount out of range"
exit
fi
for word in "${message[@]}"
do
while read -r -n 1 letter
do
if [[ "$letter" = [a-z] ]]
then
for a in "${!abc_small[@]}"
do
if [ "${abc_small[$a]}" = "$letter" ]
then
a=$(echo "($a + $shift_amount) % 26" | bc)
echo -n "${abc_small[$a]}"
fi
done
elif [[ "$letter" = [A-Z] ]]
then
for a in "${!abc_cap[@]}"
do
if [ "${abc_cap[$a]}" = "$letter" ]
then
a=$(echo "($a + $shift_amount) % 26" | bc)
echo -n "${abc_cap[$a]}"
fi
done
elif [[ "$letter" = "" ]]
then echo -n " "
else echo -n "$letter"
fi
done < <(echo "$word")
done
echo
exit
【讨论】: