Bash 尝试使用类似rot13的解决方案来处理特殊字符

Bash 尝试使用类似rot13的解决方案来处理特殊字符,bash,sed,tr,Bash,Sed,Tr,我想实现一个使用随机生成的alpha-num键的rot13函数,但我还想包含特殊字符,似乎无法实现。使用包含特殊字符的tr命令的此功能不起作用: echo "$@" | tr "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789!@#$%^&*()-_=+\|" "A*KWx#o(5I-j\e|Hv)X7R0SJ=8+tBE^ucOVgMd2l$QkafU4nqz36LPhGb1rmswi%FC@!D_p9N&am

我想实现一个使用随机生成的alpha-num键的rot13函数,但我还想包含特殊字符,似乎无法实现。使用包含特殊字符的
tr
命令的此功能不起作用:

echo "$@" | tr "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789!@#$%^&*()-_=+\|" "A*KWx#o(5I-j\e|Hv)X7R0SJ=8+tBE^ucOVgMd2l$QkafU4nqz36LPhGb1rmswi%FC@!D_p9N&YyZT"
因此,我编写了一个更复杂的函数,它将一个单词的字母拆分成一个数组,然后将每个数组元素传递给一个
for
循环,该循环由92个if/elif语句组成,当匹配一个字符时,会运行一个
sed
replace子循环:

conv=""
x="$1" ; echo "\$1: ${1}"
i=0
while [ $i -lt ${#x} ]; do y[$i]=${x:$i:1};  i=$((i+1));done
for f in "${y[@]}" ; do
    newF=$(echo "$f"|if [[ "$f" == "a" ]] ; then sed -r 's/a/7/g' ; elif [[ "$f" == "A" ]] ; then sed -r 's/A/\?/g' ; elif [[ "$f" == "b" ]] ; then sed -r 's/b/v/g' ; elif [[ "$f" == "B" ]] ; then sed -r 's/B/\./g' ; elif [[ "$f" == "c" ]] ; then sed -r 's/c/q/g' ; elif [[ "$f" == "C" ]] ; then sed -r 's/C/2/g' ; elif [[ "$f" == "d" ]] ; then sed -r 's/d/m/g' ; elif [[ "$f" == "D" ]] ; then sed -r 's/D/\Z/g' ; elif [[ "$f" == "e" ]] ; then sed -r 's/e/S/g' ; elif [[ "$f" == "E" ]] ; then sed -r 's/E/y/g' ; elif [[ "$f" == "f" ]] ; then sed -r 's/f/d/g' ; elif [[ "$f" == "F" ]] ; then sed -r 's/F/\)/g' ; elif [[ "$f" == "g" ]] ; then sed -r 's/g/z/g' ; elif [[ "$f" == "G" ]] ; then sed -r 's/G/K/g' ; elif [[ "$f" == "h" ]] ; then sed -r 's/h/T/g' ; elif [[ "$f" == "H" ]] ; then sed -r 's/H/\{/g' ; elif [[ "$f" == "i" ]] ; then sed -r 's/i/8/g' ; elif [[ "$f" == "I" ]] ; then sed -r 's/I/H/g' ; elif [[ "$f" == "j" ]] ; then sed -r 's/j/p/g' ; elif [[ "$f" == "J" ]] ; then sed -r 's/J/A/g' ; elif [[ "$f" == "k" ]] ; then sed -r 's/k/@/g' ; elif [[ "$f" == "K" ]] ; then sed -r 's/K/R/g' ; elif [[ "$f" == "l" ]] ; then sed -r 's/l/W/g' ; elif [[ "$f" == "L" ]] ; then sed -r 's/L/9/g' ; elif [[ "$f" == "m" ]] ; then sed -r 's/m/s/g' ; elif [[ "$f" == "M" ]] ; then sed -r 's/M/\(/g' ; elif [[ "$f" == "n" ]] ; then sed -r 's/n/V/g' ; elif [[ "$f" == "N" ]] ; then sed -r 's/N/t/g' ; elif [[ "$f" == "o" ]] ; then sed -r 's/o/\\/g' ; elif [[ "$f" == "O" ]] ; then sed -r 's/O/\!/g' ; elif [[ "$f" == "p" ]] ; then sed -r 's/p/=/g' ; elif [[ "$f" == "P" ]] ; then sed -r 's/P/n/g' ; elif [[ "$f" == "q" ]] ; then sed -r 's/q/#/g' ; elif [[ "$f" == "Q" ]] ; then sed -r 's/Q/e/g' ; elif [[ "$f" == "r" ]] ; then sed -r 's/r/g/g' ; elif [[ "$f" == "R" ]] ; then sed -r 's/R/f/g' ; elif [[ "$f" == "s" ]] ; then sed -r 's/s/-/g' ; elif [[ "$f" == "S" ]] ; then sed -r 's/S/0/g' ; elif [[ "$f" == "t" ]] ; then sed -r 's/t/,/g' ; elif [[ "$f" == "T" ]] ; then sed -r 's/T/:/g' ; elif [[ "$f" == "u" ]] ; then sed -r 's/u/_/g' ; elif [[ "$f" == "U" ]] ; then sed -r 's/U/Q/g' ; elif [[ "$f" == "v" ]] ; then sed -r 's/v/i/g' ; elif [[ "$f" == "V" ]] ; then sed -r 's/V/k/g' ; elif [[ "$f" == "w" ]] ; then sed -r 's/w/w/g' ; elif [[ "$f" == "W" ]] ; then sed -r 's/W/l/g' ; elif [[ "$f" == "x" ]] ; then sed -r 's/x/3/g' ; elif [[ "$f" == "X" ]] ; then sed -r 's/X/\]/g' ; elif [[ "$f" == "y" ]] ; then sed -r 's/y/5/g' ; elif [[ "$f" == "Y" ]] ; then sed -r 's/Y/O/g' ; elif [[ "$f" == "z" ]] ; then sed -r 's/z/F/g' ; elif [[ "$f" == "Z" ]] ; then sed -r 's/Z/"/g' ; elif [[ "$f" == "0" ]] ; then sed -r 's/0/;/g' ; elif [[ "$f" == "1" ]] ; then sed -r 's/1/E/g' ; elif [[ "$f" == "2" ]] ; then sed -r 's/2/>/g' ; elif [[ "$f" == "3" ]] ; then sed -r 's/3/u/g' ; elif [[ "$f" == "4" ]] ; then sed -r 's/4/\$/g' ; elif [[ "$f" == "5" ]] ; then sed -r 's/5/</g' ; elif [[ "$f" == "6" ]] ; then sed -r 's/6/\+/g' ; elif [[ "$f" == "7" ]] ; then sed -r 's/7/x/g' ; elif [[ "$f" == "8" ]] ; then sed -r 's/8/L/g' ; elif [[ "$f" == "9" ]] ; then sed -r 's/9/C/g' ; elif [[ "$f" == "!" ]] ; then sed -r 's/\!/a/g' ; elif [[ "$f" == "@" ]] ; then sed -r 's/@/\//g' ; elif [[ "$f" == "#" ]] ; then sed -r 's/#/M/g' ; elif [[ "$f" == "$" ]] ; then sed -r "s/\$/'/g" ; elif [[ "$f" == "%" ]] ; then sed -r 's/%/1/g' ; elif [[ "$f" == "^" ]] ; then sed -r 's/\^/c/g' ; elif [[ "$f" == "&" ]] ; then sed -r 's/\&/h/g' ; elif [[ "$f" == "*" ]] ; then sed -r 's/\*/U/g' ; elif [[ "$f" == "(" ]] ; then sed -r 's/\(/\|/g' ; elif [[ "$f" == ")" ]] ; then sed -r 's/\)/\[/g' ; elif [[ "$f" == "-" ]] ; then sed -r 's/-/I/g' ; elif [[ "$f" == "_" ]] ; then sed -r 's/_/\*/g' ; elif [[ "$f" == "=" ]] ; then sed -r 's/=/G/g' ; elif [[ "$f" == "+" ]] ; then sed -r 's/\+/P/g' ; elif [[ "$f" == "|" ]] ; then sed -r 's/\|/o/g' ; elif [[ "$f" == '\' ]] ; then sed -r 's/\\/Y/g' ; elif [[ "$f" == "[" ]] ; then sed -r 's/\[/j/g' ; elif [[ "$f" == "{" ]] ; then sed -r 's/\{/B/g' ; elif [[ "$f" == "]" ]] ; then sed -r 's/\]/\%/g' ; elif [[ "$f" == "}" ]] ; then sed -r 's/\}/J/g' ; elif [[ "$f" == ";" ]] ; then sed -r 's/;/X/g' ; elif [[ "$f" == ":" ]] ; then sed -r 's/:/\^/g' ; elif [[ "$f" == "'" ]] ; then sed -r "s/'/D/g"; elif [[ "$f" == '"' ]] ; then sed -r 's/"/\}/g' ; elif [[ "$f" == "," ]] ; then sed -r 's/,/4/g' ; elif [[ "$f" == "<" ]] ; then sed -r 's/</r/g' ; elif [[ "$f" == "." ]] ; then sed -r 's/\./N/g' ; elif [[ "$f" == ">" ]] ; then sed -r 's/>/\&/g' ; elif [[ "$f" == "/" ]] ; then sed -r 's/\//6/g' ; elif [[ "$f" == "?" ]] ; then sed -r 's/\?/b/g' ; fi)
    echo "converting: $f to $newF"
    conv="${conv}${newF}" ; echo "\$conv: ${conv}"
done
结果是:

\Ps63 kD_c0o
但应该是:

|5iPL fp9VJo
我错误地用x表示“e”而不是“3”,因此:

|GiPL fp9VJo
全靠两个地方。我可能会想出一个方法来计算逃逸的字符并进行相应的调整,但奇怪的是,合并特殊字符应该如此困难。我甚至尝试将它们放入数组元素中,这也不是一个坏方法,但bash也对此犹豫不决

我一直在使用电子表格尽可能地简化char x-references。但在这里它们是并排的:

a <=> A   n <=> +   0 <=> L  
A <=> *   N <=> t   1 <=> P  
b <=> K   o <=> B   2 <=> h  
B <=> W   O <=> E   3 <=> G  
c <=> x   p <=> ^   4 <=> b  
C <=> #   P <=> u   5 <=> 1  
d <=> o   q <=> c   6 <=> r  
D <=> (   Q <=> O   7 <=> m  
e <=> 5   r <=> V   8 <=> s  
E <=> I   R <=> g   9 <=> w  
f <=> -   s <=> M   ! <=> i  
F <=> j   S <=> d   @ <=> %  
g <=> \   t <=> 2   # <=> F  
G <=> e   T <=> l   $ <=> C  
h <=> |   u <=> $   % <=> @  
H <=> H   U <=> Q   ^ <=> !  
i <=> v   v <=> k   & <=> D  
I <=> )   V <=> a   * <=> _  
j <=> X   w <=> f   ( <=> p  
J <=> 7   W <=> U   ) <=> 9  
k <=> R   x <=> 4   - <=> N  
K <=> 0   X <=> n   _ <=> &  
l <=> S   y <=> q   = <=> Y  
L <=> J   Y <=> z   + <=> y  
m <=> =   z <=> 3   | <=> Z  
M <=> 8   Z <=> 6   \ <=> T
脚本返回:

$convRes: 2_b@m{hWe*0

我最初希望的结果是使用
tr
,如果可以使用比包含特殊字符更简单的解决方案,我会使用它,但我所有的尝试都没有成功。可能我只是查看和编辑同一个命令太长太多次,无法看到简单的解决方案。

使用“tr”的原始解决方案存在两个问题:

  • 您使用的是双引号,但是里面有一个$,这是shell所特有的
  • 您的翻译不是对称的:a被翻译为a,但a被翻译为*
  • 我可能会使用sed-e'y//'(或者python)来实现这一点,但tr的一个优点是可以使用字符集:

    tr '[:upper:][:lower:]' '[:lower:][:upper:]'
    

    但无论哪种方式,您都必须自己列出特殊字符对。

    使用“tr”的原始解决方案存在两个问题:

  • 您使用的是双引号,但是里面有一个$,这是shell所特有的
  • 您的翻译不是对称的:a被翻译为a,但a被翻译为*
  • 我可能会使用sed-e'y//'(或者python)来实现这一点,但tr的一个优点是可以使用字符集:

    tr '[:upper:][:lower:]' '[:lower:][:upper:]'
    

    但无论哪种方法,您都必须自己列出特殊字符对。

    问题是,首先您需要在
    tr
    参数周围使用单引号,以防止
    bash
    在字符串中展开
    $
    。另外,您忘记了
    tr
    专门处理几个字符:

    • 破折号
      -
      创建字符集
    • 反斜杠可以逃避后面的任何内容
    这通过反斜杠避开破折号和反斜杠解决了这些问题

    tr 'aAbBcCdDeEFGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789!@#$%^&*()\-_=+\\|' \
       'A*KWx#o(5I\-j\\e|Hv)X7R0SJ=8+tBE^ucOVgMd2l$QkafU4nqz36LPhGb1rmswi%FC@!D_p9&YyT' 
    
    它在我的
    mingw
    bash
    中运行良好

    您没有使用方括号
    [
    ,但如果以后使用,请注意,如果不使用,这些方括号也会导致问题

    添加

    解决OP断言这不正确的问题,我看不出如何解决。使用上面的转义字符串,但删除反斜杠以显示等价性:

    Plain:  aAbBcCdDeEFGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789!@#$%^&*()-_=+\|
    Cypher: A*KWx#o(5I-j\e|Hv)X7R0SJ=8+tBE^ucOVgMd2l$QkafU4nqz36LPhGb1rmswi%FC@!D_p9&YyT
    
    手工翻译:

    h3!10 w()rLd
    \Ps63 kD_c0o
    
    然而OP的“应该”字符串是不同的。也许我不明白我们想要实现什么

    实施OP的新表格

    您的新表不是您在
    tr
    命令行中拥有的表。下面是相应的翻译(我从一个小Ruby脚本中获得,并将您的表作为输入):

    请注意,这只是水平显示的表格。没有什么特别之处

    结果是添加了反斜杠转义的
    tr
    命令

    echo 'h3!10 w()rLd' | \
    tr 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789!@#$%^&*()\-_=+|\\' \
       'A*KWx#o(5I\-j\\e|Hv)X7R0SJ=8+tBE^ucOVgMd2l$QkafU4nqz36LPhGb1rmswi%FC@!D_p9N&YyZT'
    
    我的盒子上印着:

    |GiPL fp9VJo
    
    或者将参数切换到另一个方向(因为您的密码不是对称的)

    这就产生了

    h3!10 w()rLd
    

    在我的框中,正如您所期望的。

    问题是首先,您需要在
    tr
    参数周围使用单引号,以防止
    bash
    在字符串中展开
    $
    。此外,您忘了
    tr
    特别处理一些字符:

    • 破折号
      -
      创建字符集
    • 反斜杠可以逃避后面的任何内容
    这通过反斜杠避开破折号和反斜杠解决了这些问题

    tr 'aAbBcCdDeEFGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789!@#$%^&*()\-_=+\\|' \
       'A*KWx#o(5I\-j\\e|Hv)X7R0SJ=8+tBE^ucOVgMd2l$QkafU4nqz36LPhGb1rmswi%FC@!D_p9&YyT' 
    
    它在我的
    mingw
    bash
    中运行良好

    您没有使用方括号
    [
    ,但如果以后使用,请注意,如果不使用,这些方括号也会导致问题

    添加

    解决OP断言这不正确的问题,我看不出如何解决。使用上面的转义字符串,但删除反斜杠以显示等价性:

    Plain:  aAbBcCdDeEFGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789!@#$%^&*()-_=+\|
    Cypher: A*KWx#o(5I-j\e|Hv)X7R0SJ=8+tBE^ucOVgMd2l$QkafU4nqz36LPhGb1rmswi%FC@!D_p9&YyT
    
    手工翻译:

    h3!10 w()rLd
    \Ps63 kD_c0o
    
    然而OP的“应该”字符串是不同的。也许我不明白我们想要实现什么

    实施OP的新表格

    您的新表不是您在
    tr
    命令行中拥有的表。下面是相应的翻译(我从一个小Ruby脚本中获得,并将您的表作为输入):

    请注意,这只是水平显示的表格。没有什么特别之处

    结果是添加了反斜杠转义的
    tr
    命令

    echo 'h3!10 w()rLd' | \
    tr 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789!@#$%^&*()\-_=+|\\' \
       'A*KWx#o(5I\-j\\e|Hv)X7R0SJ=8+tBE^ucOVgMd2l$QkafU4nqz36LPhGb1rmswi%FC@!D_p9N&YyZT'
    
    我的盒子上印着:

    |GiPL fp9VJo
    
    或者将参数切换到另一个方向(因为您的密码不是对称的)

    这就产生了

    h3!10 w()rLd
    

    在我的框中,正如您所期望的。

    尝试在
    tr
    字符串周围加上单引号。否则,您必须用反斜杠转义特殊字符。您在其他字符串中这样做了。
    tr
    命令会很好地工作,如果您提供正确的参数。@Gene实际上我一直在玩它,直到我的头感觉它会爆炸。我