如何转换传递给脚本的字符串的替代字符,如果它较低,则应将其转换为高字符,如果为高则转换为下部?
read -p " Enter string" str
for i in `seq 0 ${#str}`
do
#echo $i
rem=$(($i % 2 ))
if [ $rem -eq 0 ]
then
echo ${str:$i:1}
else
fr=${str:$i:1}
if [[ "$fr" =~ [A-Z] ]]
then
echo ${str:$i:1} | tr '[:upper:]' '[:lower:]'
elif [[ "$fr" =~ [a-z] ]]
then
echo ${str:$i:1} | tr '[:lower:]' '[:upper:]'
else
echo ""
fi
fi
done
你的问题有点挑战,因为它被标记为shell
,而不是与 bash 或 zsh 等高级 shell 有关的问题。在 POSIX shell 中,您没有字符串索引,没有 C 样式的for
循环,也没有使用字符类模式匹配的[[ .. ]]
运算符。
但是,通过一些笨拙的创造力,旧的expr
和POSIX字符串和算术运算,并将字符串限制为ASCII字符,您可以迭代字符串,将大写更改为小写,小写和大写,同时保持所有其他字符不变。
如果您有可用的高级 shell,我不推荐这种方法,但如果您仅限于 POSIX shell,因为您的问题被标记,它会起作用,但不要指望它会超快......
#!/bin/sh
a=${1:-"This Is My 10TH String"} ## input and output strings
b=
i=1 ## counter and string length
len=$(expr length "$a")
asciiA=$(printf "%d" "'A") ## ASCII values for A,Z,a,z
asciiZ=$(printf "%d" "'Z")
asciia=$(printf "%d" "'a")
asciiz=$(printf "%d" "'z")
echo "input : $a" ## output original string
while [ "$i" -le "$len" ]; do ## loop over each character
c=$(expr substr "$a" "$i" "1") ## extract char from string
asciic=$(printf "%d" "'$c") ## convert to ASCII value
## check if asciic is [A-Za-z]
if [ "$asciiA" -le "$asciic" -a "$asciic" -le "$asciiZ" ] ||
[ "$asciia" -le "$asciic" -a "$asciic" -le "$asciiz" ]
then ## toggle the sign bit (bit-6)
b="${b}$(printf "x$(printf "%x" $((asciic ^ 1 << 5)))n")"
else
b="$b$c" ## otherwise copy as is
fi
i=$(expr $i + 1)
done
echo "output: $b" ## output resluting string
大小写更改是通过依赖每个大写或小写字符的 ASCII 值中大小写位 (bit-6) 的简单位切换来将其从小写更改为大写,反之亦然。(请注意,您可以将printf
和位移换成asciic
的tr
作为替代方案)
示例使用/输出
$ sh togglecase.sh
input : This Is My 10TH String
output: tHIS iS mY 10th sTRING
当您想每隔一个字符大小写擦拭一次时,请尝试以下操作:
read -p " Enter string " str
for i in `seq 0 ${#str}`; do
rem=$(($i % 2 ))
if [ $rem -eq 0 ]
then
printf "%s" "${str:$i:1}"
else
fr=${str:$i:1}
printf "%s" "$(tr '[:upper:][:lower:]' '[:lower:][:upper:]' <<< "${str:$i:1}")"
fi
done
echo
编辑:第二种解决方案 切换 str 的大小写并合并新旧字符串。
#!/bin/bash
str="part is lowercase & PART IS UPPERCASE"
str2=$(tr '[:upper:][:lower:]' '[:lower:][:upper:]' <<< "${str}")
str_chopped=$(sed -r 's/(.)./1n/g' <<< "${str}");
# Will have 1 additional char for odd length str
# str2_chopped_incorrect=$(sed -r 's/.(.)/1n/g' <<< "${str2}");
str2_chopped=$(fold -w2 <<< "${str2}" | sed -nr 's/.(.)/1/p' );
paste -d 'n' <(echo "${str_chopped}") <(echo "${str2_chopped}") | tr -d 'n'; echo