如何通过SED适当地传递关联的数组值



我正在创建一个凯撒密码,如果字母表颠倒,它会用匹配的字母替换单词中的字母。样本为"abcdefghijklmnopqrstuvxyz"。以下代码的输出产生"abcdefghijklmlkjihgfedcba"。所需的输出是反向的字母表,但一旦编辑器到达中点,它就会反向返回,而不是一直到最后。

declare -A origin
x=({a..z})
z=({z..a})
for i in {0..25}
do
origin[${x[i]}]=${z[i]}
done
for x in "${!origin[@]}"
do
sed -i 's/'${x}'/'${origin[${x}]}'/g' test.txt
done

不要忘记bash中的字符索引。在脚本中,不需要前两个索引数组x & y。示例:

declare -A origin
x=abcdefghijklmnopqrstuvwxyz
z=zyxwvutsrqponmlkjihgfedcba
for i in {0..25}; do
origin[${x:i:1}]=${z:i:1}
done

没有什么比用origin[{a..z}]代替{z..a}并得到一个熟悉的回顾结果更好的了吗?例如,只查看第一次最后一次一次迭代中,用z替换所有a。然后,在上一次迭代中,您再次用a替换所有z(包括您之前在第一次迭代中替换的a->z),从而有效地撤消您的更改。

一个更好的例子是查看字母表m->n的中点。

x=abcdefghijklmnopqrstuvwxyz
z=zyxwvutsrqponmlkjihgfedcba
||

当迭代达到m时,用n替换所有的m。然后在下一次迭代中,将n的替换为m的。

你可以看到,这看起来就像只有一半的换人受到影响。到达原点中点后,任何替换只发生一次,因为您不再遇到已经替换的字母。

之前发布的使用tr的解决方案看起来是您的最佳选择之一。

用于传递关联数组的方法是正确的,但Ceasar密码的逻辑是错误的。

因为对于for循环的每次迭代,sed命令都会更改输入文件中的一些字符。该字符可以是输入文件中的原始字符,也可以是以前由sed更改的字符。因此,for循环实际上会进行多次转换,而不是进行一次转换。

例如

考虑输入文件

$ cat test
a z

现在一个小的格式化脚本将是

for x in "${origin[@]}"; do     sed -i  "s/$x/${origin[$x]}/g" test; echo "$x ${origin[$x]}";  done; 
z a
y b
x c
w d
v e
..
..

在第一次迭代中,sed会将z更改为a。现在输入文件将是

$cat test
a a

现在,在第25次迭代时,$x将为a,这将把输入中的两个a转换为z

$ cat test
z z

替代解决方案

可以使用tr作为编写替代解决方案

$ a=$(echo {z..a} | tr -d " ")
$ b=$(echo {a..z} | tr -d " ")
$ echo {a..z} | tr $b $a
z y x w v u t s r q p o n m l k j i h g f e d c b a

为什么它有效?

这里的字符是从输入中读取的,并用tr参数中的相应字符进行更改,这确保了单个字符只更改一次。

我找到了这个问题的解决方案。谢谢你们两个的帮助!

#!/bin/bash
#Retrieve the desired shift from user
echo "What number do you want to use for the shift?"
read num
#Create an array of all letters
x=({a..z})
#Take user input and use to create the cipher array
case "$num" in
0)
y=({a..z})
;;
1)
y=({{b..z},a})
;;
2)
y=({{c..z},a,b})
;;
3)
y=({{d..z},a,b,c})
;;
4)
y=({{e..z},a,b,c,d})
;;
5)
y=({{f..z},{a..e}})
;;
6)
y=({{g..z},{a..f}})
;;  
7)
y=({{h..z},{a..g}})
;;
8)
y=({{i..z},{a..h}})
;;
9)
y=({{j..z},{a..i}})
;;
10)
y=({{k..z},{a..j}})
;;
11)
y=({{l..z},{a..k}})
;;
12)
y=({{m..z},{a..l}})
;;
13)
y=({{n..z},{a..m}})
;;
14)
y=({{o..z},{a..n}})
;;
15)
y=({{p..z},{a..o}})
;;
16)
y=({{q..z},{a..p}})
;;
17)
y=({{r..z},{a..q}})
;;
18)
y=({{s..z},{a..r}})
;;
19)
y=({{t..z},{a..s}})
;;
20)
y=({{u..z},{a..t}})
;;
21)
y=({{v..z},{a..u}})
;;
22)
y=({{w..z},{a..v}})
;;
23)
y=({{x..z},{a..w}})
;;
24)
y=({{y..z},{a..x}})
;;
25)
y=({{z..z},{a..y}})
;;
*)
echo "Sorry, you must use a shift from 0 to 25."
;;
esac
#create the string variables for manipulation
fromset=""
toset=""
#place the alphabetic arrays into the atring variables
for i in {0..25}
do
fromset="$fromset${x[i]}"
toset="$toset${y[i]}"
done
#Use sed text transformations to alter given files
sed "y/$fromset/$toset/" original.txt > encoded.txt
sed "y/$toset/$fromset/" encoded.txt > decoded.txt

相关内容

  • 没有找到相关文章

最新更新