Ваш вопрос немного сложен, учитывая, что он помечен shell
, а не как вопрос, относящийся к расширенной оболочке, такой как bash или zsh. В оболочке POSIX у вас нет строковых индексов , нет цикла C-style for
и оператора [[ .. ]]
для использования сопоставления с образцом класса символов.
Однако, немного неуклюжий, со старыми строковыми и арифметическими операциями expr
и POSIX и ограничением строк символов до символов ASCII, вы можете перебирать строку, изменяя заглавные буквы на строчные и строчные и прописные , оставляя все остальные символы без изменений.
Я бы не рекомендовал этот подход, если у вас есть расширенная оболочка, но если вы ограничены оболочкой POSIX, поскольку ваш вопрос помечен, он будет работать, но не ожидайте, что он будет очень быстрым .. .
#!/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
На изменение регистра влияет простое переключение бит регистра регистра (бит-6) в значении ASCII каждого символа верхнего или нижнего регистра, чтобы изменить его с нижнего на верхний или наоборот. (и обратите внимание, вы можете обменять printf
и битовое смещение на tr
на asciic
в качестве альтернативы)
Пример использования / Вывод
$ sh togglecase.sh
input : This Is My 10TH String
output: tHIS iS mY 10th sTRING