Чувствительность к регистру в сценариях оболочки

10

Рассмотрим этот сценарий 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', вывод будет буквой нижнего регистра , и это будет одинаково для 'A' ... Как мне это преодолеть?

    
задан Ramana Reddy 13.03.2015 в 12:27
источник

2 ответа

20
#!/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  

Для получения дополнительной информации о регулярном выражении в нижнем регистре [az] и регулярном выражении верхнего регистра [AZ] в bash см. Почему это не относится к регистру, когда nocasematch отключен? .     

ответ дан karel 13.03.2015 в 13:31
источник
22

Проблема состоит в том, что диапазон символов [a-z] фактически включает в себя буквы верхнего регистра. Это объясняется в руководстве bash :

  

В выражении скобки выражение диапазона состоит из двух символов, разделенных дефисом. Он соответствует любому одиночному символу, который сортирует между двумя символами, включительно. В локали C по умолчанию последовательность сортировки - это собственный порядок символов; например, '[a-d]' эквивалентно '[abcd]'. В других локалях последовательность сортировки не указана, а «[ad]» может быть эквивалентной «[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.

    
ответ дан terdon 13.03.2015 в 13:54