Любая программа - это автомат, предназначенный для обработки данных: получая на входе одну информацию, они в результате работы выдают другую. Хотя входящая и/или выходящая информация может быть и нулевой, т. е. попросту отсутствовать. Те данные, которые передаются программе для обработки - это ее ввод, то, что она выдает в результате работы - вывод. Организация ввода и вывода для каждой программы - это задача операционной системы.
Каждая программа работает с данными определенного типа: текстовыми, графическими, звуковыми и т. п. Как, наверное, уже стало понятно из предыдущих лекций, основной интерфейс управления системой в Linux - это терминал, который предназначен для передачи текстовой информации от пользователя системе и обратно (см. лекцию 2). Поскольку ввести с терминала и вывести на терминал можно только текстовую информацию, то ввод и вывод программ, связанных с терминалом1), тоже должен быть текстовым. Однако необходимость оперировать с текстовыми данными не ограничивает возможности управления системой, а, наоборот, расширяет их. Человек может прочитать вывод любой программы и разобраться, что происходит в системе, а разные программы оказываются совместимыми между собой, поскольку используют один и тот же вид представления данных - текстовый. Возможностям, которые дает Linux при работе с данными в текстовой форме, и посвящена данная лекция.
"Текстовость" данных - всего лишь договоренность об их формате. Никто не мешает выводить на экран нетекстовый файл, однако пользы в этом будет мало. Во-первых, раз уж файл содержит не текст, то не предполагается, что человек сможет что-либо понять из его содержимого. Во-вторых, если в нетекстовых данных, выводимых на терминал, случайно встретится управляющая последовательность, терминал ее выполнит. Например, если в скомпилированной программе записано число 1528515121, оно представлено в виде четырех байтов: 27, 91, 49 и 74. Соответствующий им текст состоит из четырех символов ASCII: "esc", "[", "1" и "J", и при выводе файла на виртуальную консоль Linux в этом месте выполнится очистка экрана, так как "^[[1J" - именно такая управляющая последовательность для виртуальной консоли. Не все управляющие последовательности столь безобидны, поэтому использовать нетекстовые данные в качестве текстов не рекомендуется.
Что же делать, если содержимое нетекстового файла все-таки желательно просмотреть (то есть превратить в текст)? Можно воспользоваться программой hexdump, которая выдает содержимое файла в виде шестнадцатеричных ASCII-кодов, или strings, показывающей только те части файла, которые могут быть представлены в виде текста:
[methody@localhost methody]$ hexdump -C /bin/cat | less 00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 02 00 03 00 01 00 00 00 90 8b 04 08 34 00 00 00 |............4...| 00000020 e0 3a 00 00 00 00 00 00 34 00 20 00 07 00 28 00 |Ю:......4. ...(.| . . . 00000100 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 |................| 00000110 04 00 00 00 2f 6c 69 62 2f 6c 64 2d 6c 69 6e 75 |..../lib/ld-linu| 00000120 78 2e 73 6f 2e 32 00 00 04 00 00 00 10 00 00 00 |x.so.2..........| 00000130 01 00 00 00 47 4e 55 00 00 00 00 00 02 00 00 00 |....GNU.........| . . . [methody@localhost methody]$ strings /bin/cat | less /lib/ld-linux.so.2 _Jv_RegisterClasses __gmon_start__ libc.so.6 stdout . . . [methody@localhost methody]$ strings -n3 /bin/cat | less /lib/ld-linux.so.2 GNU _Jv_RegisterClasses __gmon_start__ libc.so.6 stdout . . .
Пример 7.1. Использование hexdump и strings
В примере Мефодий, зная заранее, что текста будет выдано много, воспользовался конвейером "| less", описанным в разделе "Конвейер". С ключом "-C" утилита hexdump выводит в правой стороне экрана текстовое представление данных, заменяя непечатные символы точками (чтобы среди выводимого текста не встретилось управляющей последовательности). Мефодий заметил, что strings "не нашла" в файле /bin/cat явно текстовых подстрок "ELF" и "GNU": первая из них - вообще не текст (перед ней стоит непечатный символ с кодом 7f, а после - символ с кодом 1), а вторая - слишком короткая, хоть и ограничена символами с кодом 0, как это и полагается строке в скомпилированной программе. Наименьшая длина строки передается strings ключом "-n".