我已经完成了一个脚本,为每个字母定义一个变量(用于加密过程),但我希望空格位于输出中。
我有这个:
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..)
你能帮我吗?
答案 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
我调用了此脚本banana
,chmod +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:!: