问题
So far, the code only changes the first letter. If I take the break out, then it changes each instance of a letter more than once (which is bad). I'm simply attempting a caesar cipher using sed. I realize I could use tr to perform text transformations, but I'd prefer to stick with sed.
echo "What number do you want to use for the shift?"
read num
declare -A origin
x=({a..z})
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
for i in {0..25}
do
origin[${x[i]}]=${y[i]}
done
for i in {0..25}
do
origin[${x[i]}]=${y[i]}
done
for a in "${!origin[@]}"
do
for x in "${!origin[@]}"
do
sed -i 's/'${x}'/'${origin[${x}]}'/g' test.txt
break
done
done
回答1:
The following performs a Caesar cipher (shift 3):
sed -i y/$(printf "%s" {a..z})/$(printf "%s" {d..z} {a..c})/ test.txt
Explanation
y
is sed's translate command. $(printf "%s" {a..z})
returns a string of characters. To see how it all comes together, use echo
. It shows the final sed command after bash has performed the expansions:
$ echo sed -i y/$(printf "%s" {a..z})/$(printf "%s" {d..z} {a..c})/ test.txt
sed -i y/abcdefghijklmnopqrstuvwxyz/defghijklmnopqrstuvwxyzabc/ test.txt
With this command, every occurrence of a
will be replaced by d
, every occurrence of b
will be replaced e
, and so on.
Variable Shift
The following script takes one argument, an integer. It then performs the Caesar shift for that integer:
#!/bin/bash
alpha=$( printf "%s" {a..z} )
part1=$( printf $(printf '\%03o' $(seq $((97+$1)) 122 ) ) )
part2=$( printf $(printf '\%03o' $(seq 97 $((97+$1-1)) ) ) )
sed -i y/$alpha/$part1$part2/ test.txt
For example, suppose we have this input file:
$ cat test.txt
and abc xyz
Let's perform a 4-shift:
$ bash script.sh 4
$ cat test.txt
erh efg bcd
回答2:
This code does a Caesar Cypher on a test from the command line:
#!/usr/bin/env bash
declare -i n=$1
file=$2
alphabet="abcdefghijklmnopqrstuvwxyz"
key="${alphabet:n}${alphabet:0:n}"
sed -i -e "y/${alphabet}/${key}/" ${file}
You use it like this:
$ ./caesar.sh 4 test.txt
回答3:
#!/bin/bash
#This shit works:
echo "What number do you want to use for the shift?"
read num
declare -A origin
x=({a..z})
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
fromset=""
toset=""
for i in {0..25}
do
fromset="$fromset${x[i]}"
toset="$toset${y[i]}"
done
sed "y/$fromset/$toset/" original.txt > encoded.txt
sed "y/$toset/$fromset/" encoded.txt > decoded.txt
来源:https://stackoverflow.com/questions/29886943/how-can-i-get-sed-to-change-all-of-the-instances-of-each-letter-only-once