Как различить прописные и строчные символы в операторе case?

Использование :

Для получения максимального значения сектора:

fdisk -l | awk '$6=="Linux" && v < $4{v=$4}END{print v}' 

6
28.12.2019, 23:59
2 ответа

Простой ответ, который, без сомнения, могут заменить другие.

Порядок набора символов теперь различается в зависимости от используемой локали. Концепция локали была введена для поддержки разных национальностей и их разных языков. Как вы можете видеть из вывода locale, есть несколько различных областей, которые теперь адресованы -, а не только сопоставление.

В вашем случае это США, а для целей сортировки и сопоставления используется алфавит либо AaBbCc...Zz, либо A=a, B=b, C=c и т. д. (Я забыл какой, и я не на компьютере, где я могу сверить одно с другим ). Локали очень сложны, и в некоторых локалях могут быть символы, невидимые для сортировки и сопоставления. Один и тот же символ может сортироваться по-разному в зависимости от используемой локали.

Как вы уже поняли, правильный способ определения символов нижнего регистра — [[:lower:]]; это будет включать символы с диакритическими знаками, где это необходимо, и даже символы нижнего регистра в разных алфавитах (греческом, кириллице и т. д. ).

Если вы хотите классический порядок, вы можете вернуться к приложению или даже к команде, установив LC_ALL=C. Для надуманного примера

grep some_pattern | LC_ALL=C sort | nl
6
27.01.2020, 20:27

Между порядком словаря и порядком ASCII идет непрекращающаяся битва.
Длительное время.

С точки зрения Unicode символы должны быть отсортированы по местным обычаям в их словарном порядке, таким образом, a A b B...для американских букв (буквы ASCII ). Обычно это соответствует диапазону [a -zA -Z] в локали en _US.utf -8. Интернационалисты обычно соглашаются с этим.

С точки зрения программистов, из-за языка C, [a -z] должен соответствовать только символам ascii от 97 до 122 как одно байтовое значение. Аналогично для [A -Z]. Обычно это соответствует определению символа в языке C как одного байта. Некоторые сценаристы хотят использовать это определение.

Эта битва время от времени переходила из одной интерпретации в другую.
Иногда диапазон [a -z] становится только abcdefghijklmnopqrstuvwxyz.
Иногда он переходит на aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYz.
Или к какому-то другому, более сложному списку.

Детали сложны. История длинная. Битва все еще бушует.


Итак, вы можете (проверить строкуbook):

  • «ваша строка начинается с заглавной буквы» для bash версий 2, 3 и 4 и
  • «ваша строка начинается со строчной буквы» для bash версии 5 (и 1)
  • Большинство оболочек сообщают это как "строчную букву".

Если вы проверите строкуúber(в en _US.UTF -8 ), вы получите:

  • "строчные буквы" в ksh/ATT -sh
  • «Не английская буква» в тире, zsh, bash 5.0+ или [lm]ksh.
  • «Заглавная буква» в bash 2,3 и 4.

А также строка Úber.

Итак, результат разный.

Вы также можете установить LC _ALL=C, чтобы принудительно интерпретировать a-zтолько строчные буквы (и A-Zтолько прописные буквы ). Это заморозит сопоставление, используемое только для C. Никаких изменений, если локаль изменится. Более надежный сценарий, но менее адаптивный.

Также можно использовать [[:lower:]], ноопять же, гарантируется, что это диапазон ASCII a -z только в локали C. Он может быть применен ко всем локали в будущих версиях POSIX (, но еще не опубликован в 2020 году ).

Учитывая все вышесказанное, единственным безопасным способом гарантировать, что никакое внешнее решение (от разработчика оболочки спецификации Unix )не изменит диапазон вашего кода, будет:

# practicing case statements
echo "enter a string"
read yourstring
echo -e "your string is $yourstring\n"

low='abcdefghijklmnopqrstuvwxyz'
cap='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

case "$yourstring" in
    [$cap]* ) echo "your string begins with a Capital Letter"   ;; 
    [$low]* ) echo "your string begins with a lowercase letter" ;; 
    *)      echo "your string did not begin with an English letter" ;;
esac
2
27.01.2020, 20:27

Теги

Похожие вопросы