Рассмотрите этот сценарий Bash:
#!/bin/bash
echo Enter any character
read char
case $char in
[a-z]) echo Lower case letter
;;
[A-Z]) echo Upper case letter
;;
[0-9]) echo Number
;;
?) echo Special char
;;
*) echo You entered more than one character
;;
esac
Если я вхожу, выводом является Строчная буква, и это - то же для 'A'... Как я преодолеваю это?
#!/bin/bash
echo 'enter any character'
read char
case $char in
[[:lower:]]) echo 'lower case letter'
;;
[[:upper:]]) echo 'upper case letter'
;;
[0-9]) echo 'number'
;;
?) echo 'special char'
;;
*) echo 'u entered more than one char'
;;
esac
Для получения дополнительной информации о регулярном выражении нижнего регистра [a-z] и прописное регулярное выражение [A-Z] в ударе видит , Почему оператор выбора не чувствителен к регистру, когда nocasematch прочь? .
Проблема состоит в том, что диапазон символов [a-z]
на самом деле включает прописные буквы. Это объяснено в руководство удара:
В рамках выражения скобки, выражение диапазона состоит из двух символов, разделенных дефисом. Это соответствует любому отдельному символу что виды между этими двумя символами, включительно. В значении по умолчанию C локаль, последовательность сортировки является собственным символьным порядком; например, †[a-d] ’ эквивалентен †[abcd] ’. В других локалях не определяется последовательность сортировки, и †[a-d] ’ мог бы быть эквивалентен †[abcd] ’ или †[aBbCcDd] ’ , или это могло бы не соответствовать никакому символу или набору символов, которым это соответствует, могло бы даже быть ошибочным. Для получения традиционной интерпретации выражений скобки можно использовать вЂC’ локаль путем установки переменной среды LC_ALL на значение вЂC’.
Для иллюстрирования:
$ case B in [a-c]) echo YES;; *) echo NO;; esac
YES
$ LC_ALL=C; case B in [a-c]) echo YES;; *) echo NO;; esac
NO
Так, то, что происходит, - то, что в Вашей локали (который не является C
), [a-c]
на самом деле [aAbBcC]
. Вот почему необходимо использовать классы символов POSIX , как предложено @karel вместо этого.