Bash检测没有相应var的字符

时间:2015-02-13 20:27:59

标签: bash variables space

我已经完成了一个脚本,为每个字母定义一个变量(用于加密过程),但我希望空格位于输出中。

我有这个:

eiput_splitted="$(echo $einput | sed -e 's/\(.\)/\1\n/g')"
export eouput=""

for input in $eiput_splitted; do
    export eouput=$eouput${!input}
    //added code here
done

但我不知道如何检测循环中的空格。 我试过了

if [ $input = \  ]
if [ $input = *\ * ]
if [ $input = *"\ "* ]
if [ $input = "*\ *" ]
if [ -z ${!input+x} ] (to detect unset variables, but doesn't seem to work..)

你能帮我吗?

5 个答案:

答案 0 :(得分:1)

你可以在BASH中使用它:

while IFS= read -r ch; do 
    [[ "$ch" == " " ]] && echo "space character"
done < <(grep -o . <<< "$einput")
  • grep -o . <<< "$einput"按字符分割输入字符串
  • < <(...)称为流程替换
  • IFS=将输入字段分隔符设置为null(允许通过`read读取空间)

答案 1 :(得分:1)

因为您没有引用该字符串,所以其中的任何空格都将丢失。试试这个。

echo "$einput" |
sed -e 's/\(.\)/\1\n/g' |
while IFS= read -r input; do
    eouput="$eouput${!input}"
    :
done

根据您的进一步处理情况,我可能只在循环内部printf '%s' "${!input}",并在必要时在done之后在管道中处理其输出,以避免另一个变量。

答案 2 :(得分:1)

你的设计不是很好。你不应该像这样使用普通变量!如果您想对_*é等特殊字符进行编码,则会遇到问题。

相反,您应该使用关联数组。这是一个完整的纯Bash工作示例:

#!/bin/bash

# read message to encode on stdin and outputs message to stdout

declare -A lookup

lookup=(
   [a]=n [b]=o [c]=p [d]=q [e]=r [f]=s [g]=t [h]=u [i]=v [j]=w [k]=x
   [l]=y [m]=z [n]=a [o]=b [p]=c [q]=d [r]=e [s]=f [t]=g [u]=h [v]=i
   [w]=j [x]=k [y]=l [z]=m
)

while IFS= read -r -d '' -n 1 char; do
   if [[ -z $char ]]; then
      # null byte
      printf '\0'
   elif [[ ${lookup["$char"]} ]]; then
      # defined character
      printf '%s' "${lookup["$char"]}"
   elif [[ $char = @(' '|$'\n') ]]; then
      # space and newline
      printf '%s' "$char"
   else
      # other characters passed verbatim with warning message
      printf >&2 "Warning, character \`%s' not supported\n" "$char"
      printf '%s' "$char"
   fi
done

我调用了此脚本bananachmod +x banana和:

$ ./banana <<< "hello stackoverflow"
uryyb fgnpxbiresybj
$ ./banana <<< "uryyb fgnpxbiresybj"
hello stackoverflow

如果要对变量input的内容进行编码并将编码文本存储在变量output中,只需修改主循环:

output=
linput=$input
while [[ $linput ]]; do
   char=${linput::1}
   linput=${linput:1}
   if [[ ${lookup["$char"]} ]]; then
      # defined character
      output+=${lookup["$char"]}
   elif [[ $char = @(' '|$'\n') ]]; then
      # space and newline
      output+=$char
   else
      # other characters passed verbatim with warning message
      printf >&2 "Warning, character \`%s' not supported\n" "$char"
      output+=$char
   fi
done

在这种情况下,我省略了对空字节的检查,因为Bash变量不能包含空字节。


继续这样,您可以对任何您喜欢的字符进行编码(即使是第一个版本和换行符中的空字节)。


编辑(重新评论)。

您希望将其用于Caesar cipher脚本。您担心的是,您提示用户输入用于班次的号码,并且您不知道如何在您的情况下使用此方法。关键是生成查找表相当容易。

这是一个完整的例子:

#!/bin/bash

chrv() {
   local c
   printf -v c '\\%03o' "$1"
   printf -v "$2" "$c"
}

ansi_normal=$'\E[0m'
ansi_lightgreen=$'\E[02m'

while true; do
   printf '%s' "Encryption key (number from ${ansi_lightgreen}1$ansi_normal to ${ansi_lightgreen}26$ansi_normal): "
   read -re ekey
   if [[ $ekey = +([[:digit:]]) ]]; then
      ((ekey=10#$ekey))
      ((ekey>=1 && ekey<=26)) && break
   fi
   printf 'Bad number. Try again.\n'
done

# Build the lookup table according to this number
declare -A lookup

for i in {0..25}; do
   for u in 65 97; do
      chrv "$((i+u))" basechar
      chrv "$(((i+ekey-1)%26+u))" "lookup["$basechar"]"
   done
done

printf '%s' "Input (only ${ansi_lightgreen}letters$ansi_normal and ${ansi_lightgreen}spaces${ansi_normal}): "
IFS= read -re einput
read -n1 -rep "Do you want output to be uppercase? ${ansi_lightgreen}(y/n)$ansi_normal " oup
[[ ${oup,,} = y ]] && einput=${einput^^}

output=
linput=$einput
while [[ $linput ]]; do
   char=${linput::1}
   linput=${linput:1}
   if [[ ${lookup["$char"]} ]]; then
      # defined character
      output+=${lookup["$char"]}
   elif [[ $char = @(' '|$'\n') ]]; then
      # space and newline
      output+=$char
   else
      # other characters passed verbatim with warning message
      printf >&2 "Warning, character \`%s' not supported\n" "$char"
      output+=$char
   fi
done

printf 'Original text: %s\n' "$einput"
printf 'Encoded text: %s\n' "$output"

Pure Bash且没有子shell :)

答案 3 :(得分:0)

使用IFS=$'\n'将内部字段分隔符从空格更改为换行符。

答案 4 :(得分:0)

要迭代字符串的字符,可以使用参数扩展:

eiput='Hello World!'
H="capital letter 'h'"
l="I appear 3 times"

strlen=${#eiput}
for ((i=0; i<strlen; i++)); do
    char=${eiput:i:1}
    printf "%2d:%c:%s\n" $i "$char" "${!char}"
done
 0:H:capital letter 'h'
 1:e:
 2:l:I appear 3 times
 3:l:I appear 3 times
 4:o:
 5: :
 6:W:
 7:o:
 8:r:
 9:l:I appear 3 times
10:d:
11:!:
相关问题