Bash检测不带';没有相应的var

Bash检测不带';没有相应的var,bash,variables,space,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 但我不知道如何检测循环中的空格。 我试过了 您能帮我吗?

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

我有这个:

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
但我不知道如何检测循环中的空格。 我试过了


您能帮我吗?

使用
IFS=$'\n'
将内部字段分隔符从空格更改为换行符您可以在BASH中使用此选项:

while IFS= read -r ch; do 
    [[ "$ch" == " " ]] && echo "space character"
done < <(grep -o . <<< "$einput")
而IFS=read-rch;做
[[“$ch”==”]&&echo“空格字符”

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

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

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

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

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

你的设计不太好。您不应该像这样使用普通变量!如果要对特殊字符进行编码,如
\uu
*
等,您将遇到问题

相反,应该使用关联数组。下面是一个完整的纯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
#!/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"
我将此脚本称为
banana
chmod+xbanana
,并且:

$ ./banana <<< "hello stackoverflow"
uryyb fgnpxbiresybj
$ ./banana <<< "uryyb fgnpxbiresybj"
hello stackoverflow
在本例中,我省略了对空字节的检查,因为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
#!/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"
#/bin/bash
chrv(){
局部c
printf-v c'\\%03o'$1“
printf-v“$2”“$c”
}
ansi_normal=$'\E[0m'
ansi_lightgreen=$'\E[02m'
虽然是真的;做
printf“%s”加密密钥(从${ansi_lightgreen}1$ansi_normal到${ansi_lightgreen}26$ansi_normal的数字):
阅读-再阅读
如果[[$ekey=+([[:digit:]])];则
((ekey=10#$ekey))
((ekey>=1&&ekey&2)警告,不支持字符\`%s'\n”“$char”
输出+=$char
fi
完成
printf'原始文本:%s\n'$einput'
printf'编码文本:%s\n'$output'

纯Bash,没有子shell
:)

好的。我了解你的大部分代码,但不是全部。什么是“read-rch”?(对不起,我是初学者…)还有,放x和y是一样的吗?是的,谢谢!你节省了我很多时间!这大约是你原来的和@anubhava的主要重构之间的一半。它避免了令人讨厌的临时变量,并且到处引用,并且
IFS=read-r
逐字读取每个输入标记。嘿。首先,感谢你的参与是时候回答我了。问题是每个字母都有对应的另一个字母,但它是由脚本提示的(使用加密密钥,这是一个凯撒密码脚本)@flife没问题:你只需要构建
查找
表,而不是硬编码。有趣的是,你向我们展示了如何提示和构建变量。很可能你采用了糟糕的设计和坏方法(我将向你解释为什么它坏了以及如何修复所有这些)。顺便说一句,我希望你能识别那里的rot13编码。
:)
。好的。请看一下:。你能通过私人消息与我联系吗?@flife抱歉,我不能私下与你联系(我的工资不太划算。
:D
)。我编辑了我的答案,以包含一个完全有效的示例(松散地)基于您当前的脚本。@flife
chrv
接受两个参数。第一个参数是数字(字符的代码点,例如,对于
a
,它是
97
)第二个是存储字符的变量名。例如,调用
chrv 97 foo
将字符
a
存储到变量
foo
中。我们使用此函数来构建查找表。
#!/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"