Командная строка Linux
Шрифт:
Достаточно просто поместить 26 букв в верхнем регистре в выражение в квадратных скобках. Но необходимость ввода всех этих символов вызывает некоторое беспокойство, поэтому предусмотрен другой способ:
[me@linuxbox ~]$ grep -h '^[A-Z]' dirlist*.txt
MAKEDEV
ControlPanel
GET
HEAD
POST
X
X11
Xorg
MAKEFLOPPIES
NetworkManager
NetworkManagerDispatcher
Мы сократили множество с 26 буквами до 3-символьного диапазона. Так можно выразить любой диапазон символов и даже несколько диапазонов, например, для поиска имен файлов,
[me@linuxbox ~]$ grep -h '^[A-Za-z0-9]' dirlist*.txt
Как следует из примеров, символ дефиса получает в диапазонах специальное значение, поэтому возникает вопрос: как включить дефис в выражение в квадратных скобках, чтобы он интерпретировался как обычный символ? Для этого достаточно поставить его в начало выражения. Например:
[me@linuxbox ~]$ grep -h '[A-Z]' dirlist*.txt
Эта команда найдет все имена файлов, содержащие буквы верхнего регистра. С другой стороны, следующее выражение:
[me@linuxbox ~]$ grep -h '[-AZ]' dirlist*.txt
найдет все имена файлов, содержащие дефис, букву A или букву Z.
Классы символов POSIX
Традиционные диапазоны символов — простой и эффективный способ определения наборов символов. К сожалению, они могут использоваться не со всеми программами. Мы не испытывали никаких проблем с диапазонами, используя программу grep, но могли бы столкнуться с ними при использовании других программ.
Вернемся к главе 4, где демонстрировалось использование групповых символов для подстановки имен файлов. Там говорилось, что можно использовать диапазоны символов почти так же, как они используются в регулярных выражениях, но есть одна проблема:
[me@linuxbox ~]$ ls /usr/sbin/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*
/usr/sbin/MAKEFLOPPIES
/usr/sbin/NetworkManagerDispatcher
/usr/sbin/NetworkManager
(В разных дистрибутивах будут получены разные списки файлов, а в некоторых даже пустой список. Эти результаты получены в Ubuntu.) Эта команда вернула ожидаемый результат — список имен файлов, начинающихся с заглавной буквы. Но следующая команда даст совершенно другой результат (здесь приведена только часть результатов):
[me@linuxbox ~]$ ls /usr/sbin/[A-Z]*
/usr/sbin/biosdecode
/usr/sbin/chat
/usr/sbin/chgpasswd
/usr/sbin/chpasswd
/usr/sbin/chroot
/usr/sbin/cleanup-info
/usr/sbin/complain
/usr/sbin/console-kit-daemon
В чем же причина? Для этой длинной истории имеется короткая версия. Во времена, когда операционная система Unix только появилась на свет, был известен только один набор символов — ASCII, и этот факт нашел свое отражение в данной особенности. В ASCII первые 32 символа (с номерами 0–31) — это управляющие символы (такие, как табуляция, забой и возврат каретки). Следующие 32 (32–63) представляют печатаемые символы, включая большинство знаков пунктуации и цифры с нуля до девяти. Следующие 32 (с номерами 64–95) представляют буквы верхнего регистра и несколько знаков пунктуации. Последние 31 (с номерами 96–127) представляют буквы нижнего регистра и еще несколько знаков пунктуации. Опираясь на эту классификацию, системы, использующие
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Этот порядок отличается от лексикографического, который выглядит так:
aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
С ростом популярности Unix за пределами США возникла необходимость в поддержке символов, не входящих в алфавит американского английского. Таблица ASCII была расширена до использования 8-битных символов, и в нее добавились символы с номерами 128–255, используемые во многих других языках. Для поддержки этой возможности в стандарт POSIX было введено понятие региона (locale), определяющее выбор набора символов для конкретного географического региона. Узнать, какой язык настроен в вашей системе, можно с помощью команды:
[me@linuxbox ~]$ echo $LANG
en_US.UTF-8
При проверке этой настройки POSIX-совместимые приложения используют лексикографический порядок, а не порядок следования символов в наборе ASCII. Это объясняет поведение команд, рассмотренное выше. Когда диапазон символов [A-Z] интерпретируется в лексикографическом порядке, он включает все алфавитные символы, кроме символа a в нижнем регистре, — именно это объясняет полученный результат.
Для частичного решения этой проблемы стандарт POSIX предусматривает несколько классов символов, описывающих диапазоны символов. Они перечислены в табл. 19.2.
Таблица 19.2. Название таблицы
Класс символов
Описание
[:alnum:]
Алфавитно-цифровые символы; эквивалент диапазона [A-Za-z0-9] в ASCII
[:word:]
То же, что и [:alnum:], с дополнительным символом подчеркивания (_)
[:alpha:]
Алфавитные символы; эквивалент диапазона [A-Za-z] в ASCII
[:blank:]
Включает символы пробела и табуляции
[:cntrl:]
Управляющие символы ASCII; включает символы ASCII с кодами от 0 до 31 и 127
[:digit:]
Цифры от 0 до 9
[:graph:]
Отображаемые символы; включает символы ASCII с кодами от 33 до 126
[:lower:]
Символы нижнего регистра
[:punct:]
Знаки пунктуации; эквивалент класса [-!"#$%&'*+,./:;<=>?@[\\\]_`{|}~] в ASCII
[:print:]
Печатаемые символы; все символы из класса [:graph:] и пробел
[:space:]
Пробельные символы, включая пробел, табуляцию, возврат каретки, перевод строки, вертикальную табуляцию и перевод формата; эквивалент класса [ \t\r\n\v\f] в ASCII
[:upper:]
Символы верхнего регистра
[:xdigit:]
Символы, используемые для представления шестнадцатеричных цифр; эквивалент класса [0-9A-Fa-f] в ASCII
возврат к традиционному порядку сортировки
Есть возможность вернуть систему к традиционному (ASCII) порядку сортировки, изменив значение переменной окружения LANG. Как было показано в предыдущем разделе, переменная LANG хранит название языка и набора символов, заданных в региональных настройках. Значение этой переменной первоначально определяется в момент, когда выбирается язык установки дистрибутива Linux.