Любая программа - это автомат, предназначенный для обработки данных: получая на входе одну информацию, они в результате работы выдают другую. Хотя входящая и/или выходящая информация может быть и нулевой, т. е. попросту отсутствовать. Те данные, которые передаются программе для обработки - это ее
Каждая программа работает с данными определенного типа: текстовыми, графическими, звуковыми и т. п. Как, наверное, уже стало понятно из предыдущих лекций, основной интерфейс управления системой в Linux - это
"Текстовость" данных - всего лишь договоренность об их формате. Никто не мешает выводить на экран нетекстовый файл, однако пользы в этом будет мало. Во-первых, раз уж файл содержит не текст, то не предполагается, что человек сможет что-либо понять из его содержимого. Во-вторых, если в нетекстовых данных, выводимых на 1528515121, оно представлено в виде четырех байтов: 27, 91, 49 и 74. Соответствующий им текст состоит из четырех esc ", " [ ", " 1 " и " J ", и при ^[[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 . . .
В примере Мефодий, зная заранее, что текста будет выдано много, воспользовался | less ", описанным в разделе " -C " утилита hexdump выводит в правой стороне экрана текстовое представление данных, заменяя непечатные strings "не нашла" в файле /bin/cat явно текстовых подстрок " " и " GNU ": первая из них - вообще не текст (перед ней стоит непечатный 7f, а после - 1 ), а вторая - слишком короткая, хоть и ограничена 0, как это и
полагается строке в скомпилированной программе. Наименьшая длина строки передается strings ключом " -n ".
Для того чтобы записать данные в файл или прочитать их оттуда, процессу необходимо сначала открыть этот файл (при открытии на запись, возможно, придется предварительно создать его). При этом процесс получает дескриптор (описатель) открытого файла - уникальное для этого процесса число, которое он и будет использовать во всех операциях записи. Первый открытый файл получит дескриптор 0, второй - 1 и так далее. Закончив работу с файлом, процесс закрывает его, при этом дескриптор освобождается и может быть использован повторно. Если процесс завершается, не закрыв файлы, за него это делает система. Строго говоря, только в операции открытия дескриптора указывается, какой именно файл будет задействован. В качестве "файла" используются и обычные файлы, и
Каждый процесс Linux получает при старте три "файла", открытых для него системой. Первый из них (дескриптор 0 ) открыт на чтение, это стандартный 1 ) - открыт на запись, это 2 ) предназначается для 3.
Дескриптор - это описатель потока данных, открытого процессом. Дескрипторы нумеруются, начиная с 0. При открытии нового потока данных его дескриптор получает наименьший из неиспользуемых в этот момент номеров. Три заранее открытых дескриптора - стандартный 0 ), 1 ) и 2 ) - выдаются при запуске.
Механизм копирования tty ): пользователь вводит команды с клавиатуры и видит сообщения на экране. Следовательно, любая команда, запускаемая из командной оболочки, будет выводить на тот же
Мефодий уже сталкивался с тем, что некоторые программы умеют выводить не только на info при указании -o " с именем файла выведет текст руководства в файл, вместо того, чтобы отображать его на мониторе. Даже если разработчиками программы не предусмотрен такой ключ, Мефодию известен и другой способ сохранить > " и указать после него имя файла. Таким образом Мефодий уже создавал короткие текстовые файлы ( cat (см. лекцию 5):
[methody@localhost methody]$ cat > textfile Это файл для примеров. ^D [methody@localhost methody]$ ls -l textfile -rw-r--r-- 1 methody methody 23 Ноя 15 16:06 textfile
От использования > " возможности самой утилиты cat, конечно, не расширились. Более того, cat в этом примере не получила от командной оболочки никаких параметров: ни знака " > ", ни последующего имени файла. В этом случае cat работала как обычно, не зная (и даже не интересуясь!), куда попадут выведенные данные: на экран монитора, в файл или куда-нибудь еще. Вместо того, чтобы самой обеспечивать доставку cat отправляет все данные на stdout ).
Подмена > ", и дескриптор этого файла передается программе cat под номером 1 ( fork() появляется два одинаковых процесса, один из которых - дочерний - должен запустить вместо себя команду (выполнить exec() ). Так вот, перед этим он закрывает стандартный вывод (дескриптор 1 освобождается) и открывает файл (с ним связывается первый свободный дескриптор, т. е. 1 ), а запускаемой команде ничего знать и не надо: ее textfile, потребуется другая операция - " >> ":
[methody@localhost methody]$ cat >> textfile Пример 1. ^D [methody@localhost methody]$ cat textfile Это файл для примеров. Пример 1. [methody@localhost methody]$
Мефодий получил именно тот результат, который ему требовался: добавил в конец уже существующего файла данные со
Аналогичным образом для передачи данных на вход программе может быть использован < " служит для перенаправления содержимого файла на sort без параметра, она будет читать строки со sort < имя_файла " подаст на sort данные из файла:
[methody@localhost methody]$ sort < textfile Пример 1. Это файл для примеров. [methody@localhost methody]$
Результат действия этой команды аналогичен команде sort textfile - разница лишь в том, что когда используется " < ", sort получает данные со textfile ", откуда они поступают. Механизм работы shell в данном случае тот же, что и при перенаправлении textfile ", запускает утилиту sort и передает ей на
Необходимо помнить, что операция " > " деструктивна: она всегда создает файл нулевой длины. Поэтому для, допустим, сортировки данных в файле надо применять последовательно sort < файл > новый_файл и mv новый_файл файл. Команда вида команда < файл > тот_же_файл просто урежет его до нулевой длины!
В качестве первого примера и упражнения на перенаправление Мефодий решил записать руководство по cat в свой файл cat.info:
[methody@localhost methody]$ info cat > cat.info info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. [methody@localhost methody]$ head -1 cat.info File: coreutils.info, Node: cat invocation, Next: tac invocation, Up: Output of entire files [methody@localhost methody]$
Удивленный Мефодий обнаружил, что вопреки его указанию отправляться в файл, две строки, выведенные командой info, все равно проникли на stderr ).
Использование 2> ":
[methody@localhost methody]$ info cat > cat.info 2> cat.stderr [methody@localhost methody]$ cat cat.stderr info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. [methody@localhost methody]$
В этот раз на cat.info, cat.stderr. Вместо " > " и " 2> " Мефодий мог бы написать " 1> " и " 2> ". Цифры в данном случае обозначают номера дескрипторов открываемых файлов. Если некая утилита ожидает получить открытый дескриптор с номером, допустим, 4, то, для того чтобы ее запустить, обязательно потребуется использовать сочетание " 4> ".
Иногда, однако, требуется объединить bash для этого имеется специальная последовательность " 2>1 ". Это означает "направить
[methody@localhost methody]$ info cat > cat.info 2>1 [methody@localhost methody]$ head -3 cat.info info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. File: coreutils.info, Node: cat invocation, Next: tac invocation, Up: Output of entire files [methody@localhost methody]$
В этом примере важен порядок перенаправлений: в командной строке Мефодий сначала указал, куда перенаправить > cat.info ") и только потом велел направить туда же 2>1 > cat.info "), результат получился бы неожиданный: в файл попал бы только 2>1 " номер " - это номер открытого дескриптора. Если бы упомянутая выше утилита, записывающая в четвертый дескриптор, была написана на shell, в ней бы использовались перенаправления вида " >4 ". Чтобы не набирать громоздкую конструкцию " > файл 2>1 " в bash используются сокращения: " > файл " или, что то же самое, " > файл ".
Иногда заведомо известно, что какие-то данные, выведенные программой, не понадобятся. Например, предупреждения со /dev/null. Все, что записывается в этот файл, просто будет выброшено и нигде не сохранится:
[methody@localhost methody]$ info cat > cat.info 2> /dev/null [methody@localhost methody]$
Точно таким же образом можно избавиться и от /dev/null.
В bash для перенаправления | ". Самый простой и наиболее распространенный случай, когда требуется использовать less ), которая позволит не торопясь пролистать весь текст, вернуться к началу и т. п.:
[methody@localhost methody]$ cat cat.info | less
Можно последовательно обработать данные несколькими разными программами, перенаправляя cmd1 | cmd2 | ... | cmdN ", которые могут показаться громоздкими и неудобными, но оказываются очень полезными и эффективными при обработке большого количества информации, как мы увидим далее в этой лекции.
Организация
cat: собственно, никакой "фильтрации" данных она не производит, она просто копирует
Данные, проходящие через
В любом дистрибутиве Linux присутствует набор стандартных утилит, предназначенных для работы с файловой системой и обработки текстовых данных. Многими из них Мефодий уже успел воспользоваться: это who, cat, ls, pwd, cp, chmod, id, sort и др. Мефодий уже успел заметить, что каждая из этих утилит предназначена для исполнения какой-то одной операции над файлами или текстом:
Принцип комбинирования элементарных операций для выполнения сложных задач унаследован Linux от операционной системы UNIX (как и многие другие принципы). Подавляющее большинство утилит UNIX не потеряли своего значения и в Linux. Все они ориентированы на работу с данными в текстовой форме, многие являются coreutils.
Работу в системе Linux почти всегда можно представить как работу с текстами. Поиск файлов и других объектов системы - это получение от
Работая с текстом в Linux, нужно принимать во внимание, что текстовые данные, передаваемые в системе, структурированы. Большинство утилит обрабатывает не непрерывный поток текста, а последовательность единиц. В текстовых данных в Linux выделяются следующие структурные единицы:
Строка - основная единица передачи текста в Linux. sort сортирует строки. Строки разделяются \n " (newline).
В одной строке может упоминаться и больше одного объекта. Если понимать объект как последовательность /home/methody " / ", то первое home ", третье - " methody ". Некоторые утилиты позволяют выбирать из строк отдельные
Минимальная единица текста -
^J " - "перевод строки", однако в других кодировках он может быть иным. Кроме того, на большинстве ^M "). Это вызвало путаницу: некоторые системы требуют, чтобы в конце текстового файла стояли оба этих символа в определенном порядке. Чтобы избежать путаницы, в UNIX (и, как следствие, в Linux) было принято единственно верное решение: содержимое файла соответствует кодировке, а при
В распоряжении пользователя Linux есть ряд утилит, выполняющих элементарные операции с единицами текста: поиск, замену, разделение и объединение строк,
Этот раздел посвящен нескольким примерам использования стандартных утилит для решения разных типичных (и не очень) задач. Примеры не следует воспринимать как исчерпывающий список возможностей, они приведены просто для демонстрации того, как можно организовать обработку данных при помощи
В европейской культуре очень большим авторитетом пользуются точные числа и количественные оценки. Поэтому пользователю часто бывает любопытно и даже необходимо точно посчитать что-нибудь многочисленное. Компьютер как нельзя лучше подходит для такой процедуры. Стандартная утилита для подсчета строк, слов и wc (от англ. "word count" - "подсчет слов"). Мефодий запомнил, что в Linux многое можно представить как слова и строки, и решил таким образом посчитать свои файлы:
[methody@localhost methody]$ find . | wc -l 42 [methody@localhost methody]$
Мефодий получил желаемое число - " 42 ". Для этого ему потребовалась команда find - рекомендованный Гуревичем инструмент поиска нужных файлов в системе. Мефодий вызвал find с одним параметром - каталогом, с которого надо начинать поиск. find выводит список найденных файлов по одному на строку, а поскольку критерии поиска в данном случае не уточнялись, то find просто вывела список всех файлов во всех подкаталогах текущего каталога (домашнего каталога Мефодия). Этот список Мефодий передал утилите wc, попросив ее посчитать количество полученных строк " -l ". В ответ wc выдала искомое число.
Задав find критерии поиска, можно посчитать и что-нибудь менее тривиальное, например, файлы, которые создавались или были изменены в определенный промежуток времени, файлы с определенным режимом доступа, с определенным именем и т. п. Узнать обо всех возможностях поиска при помощи find и подсчета при помощи wc можно из руководств по этим программам.
Иногда пользователя интересует только часть из тех данных, которые собирается выводить программа. Мефодий уже пользовался утилитой head, которая нужна, чтобы вывести только первые несколько строк файла. Не менее полезна утилита tail (англ. "хвост"), выводящая только последние строки файла. Если же пользователя интересует только определенная часть каждой строки файла - поможет утилита cut.
Допустим, Мефодию потребовалось получить список всех файлов и подкаталогов в " /etc ", которые принадлежат группе " adm ". И при этом ему почему-то нужно, чтобы найденные файлы в списке были представлены не полным путем, а только именем файла (скорее всего, это требуется для последующей автоматической обработки полученного списка):
[methody@localhost methody]$ find /etc -maxdepth 1 -group adm 2> /dev/null \ > | cut -d / -f 3 syslog.conf anacrontab [methody@localhost methody]$
Если команда получается такой длинной, что ее неудобно набирать в одну строку, можно разбить ее на несколько строк, не передавая системе: для этого в том месте, где нужно продолжить набор со следующей строки, достаточно поставить \ " и нажать Enter. При этом в начале строки bash выведет > ", означающий,
что команда еще не передана системе и PS2 ", описанной в лекции 8.
Мефодий получил нужный результат, задав параметры find - каталог, где нужно искать и параметр поиска - наибольшую допустимую глубину вложенности и группу, которой должны принадлежать найденные файлы. Ненужные /dev/null, а потом указал утилите cut, что в полученных со / " и вывести только третье etc " - содержимое второго
Зачастую пользователю нужно найти только упоминания чего-то конкретного среди данных, выводимых утилитой. Обычно эта задача сводится к поиску строк, в которых встречается определенное слово или комбинация grep. grep может искать строку в файлах, а может работать как bash, которые выполняются в системе:
[methody@susanin methody]$ ps aux | grep bash methody 3459 0.0 3.0 2524 1636 tty2 S 14:30 0:00 -bash methody 3734 0.0 1.1 1644 612 tty2 S 14:50 0:00 grep bash
Первый аргумент команды grep - та строка, которую нужно искать в bash ", а поскольку ps выводит сведения по строке на каждый процесс, Мефодий получил только процессы, в имени которых есть " bash ". Однако Мефодий неожиданно нашел больше, чем искал: в списке выполняющихся процессов присутствовали две строки, в которых встретилось слово " bash ", т. е. два процесса: один - искомый - командный интерпретатор bash, а другой - процесс поиска строки " grep bash ", запущенный Мефодием после ps. Это произошло потому, что после разбора командной строки bash запустил оба дочерних процесса, чтобы организовать ps процесс grep bash уже был запущен и тоже попал в ps. Чтобы в этом примере получить правильный результат, Мефодию следовало бы добавить в | grep -v grep, эта команда исключит из конечного grep ".
Очень часто точно не известно, какую именно комбинацию info, принят такой формат ссылок: " *Note название_узла::". В этом случае нужно искать не конкретное сочетание *Note ", за которой следует название узла (одно или несколько слов и пробелов), оканчивающееся ::"". Компьютер вполне способен выполнить такой запрос, если его сформулировать на строгом и понятном ему языке, например, на языке
[methody@susanin methody]$ info grep > grep.info 2> /dev/null [methody@susanin methody]$ grep -no "\*Note[^:]*::" grep.info 324:*Note Grep Programs:: 684:*Note Invoking:: [methody@susanin methody]$
Первый параметр grep, который взят в кавычки - это и есть info, второй параметр - имя файла, в котором нужно искать. Ключ " -o " заставляет grep выводить строку не целиком, а только ту часть, которая совпала с -n " - выводить номер строки, в которой встретилось данное совпадение.
В Note " и " ::" в Note " и " ::" в тексте. Однако некоторые * "), поставленная после элемента \ ".
Вторая звездочка обозначает, что стоящий перед ней элемент может быть повторен любое количество раз от нуля до бесконечности. В нашем случае звездочка относится к выражению в квадратных скобках - " :"". Целиком .* ") в случае, когда, например, в одной строке встречается две ссылки, вбирает подстроку от
конца первого " :", поместившиеся внутри этой подстроки, распознаются как "любые").
На языке + "), начало и конец строки (" ^ " и " $ " соответственно) и т. д. Благодаря regex(7). Однако руководство - это не учебник, поэтому чтобы научиться экономить время и усилия при помощи
grep. Очень многие программы, так или иначе работающие с текстом, в первую очередь текстовые редакторы, поддерживают
В заключение можно сказать, что
Удобство работы с потоком не в последнюю очередь состоит в том, что можно не только выборочно передавать результаты работы программ, но и автоматически заменять один текст другим прямо в потоке.
Для замены одних tr (сокращение от англ. "translate" - "преобразовывать, переводить"), работающая как
[methody@localhost methody]$ cat cat.info | tr abcdefghijklmnopqrstuvwxyz абцдефгхийклмнопкрстуввсиз \ > | tr ABCDEFGHIJKLMNOPRSTUVWXYZ АБЦДЕФГХИЙКЛМНОПКРСТУВВСИЗ | head -4 Филе: цореутилс.инфо, Ноде: цат инвоцатион, Нест: тац инвоцатион, Тп: Оутпут оф ентире филес 'цат': Цонцатенате анд врите филес =================================== [methody@localhost methody]$
Мефодий потрудился, составляя два параметра для утилиты tr: соответствия латинских букв кириллическим. Первый tr заменяет первым tr дважды: сначала чтобы заменить строчные буквы, а затем - прописные. Он мог бы сделать это и за один проход (просто добавив к параметрам прописные после строчных), но не захотел выписывать столь длинные строки. Полученному на выходе тексту вряд ли можно найти практическое применение, однако транслитерацию можно употребить и с пользой. Если не указать tr второго параметра, то все tr можно также удалить дублирующиеся
Помимо простой замены отдельных sed (сокращение от англ. "
Например, Мефодий с помощью sed может сделать более понятным для непривычного читателя список файлов, выводимый ls:
[methody@localhost methody]$ ls -l | sed s/^-[-rwx]*/Файл:/ | sed s/^d[-rwx]*/Каталог:/ итого 124 Файл: 1 methody methody 2693 Ноя 15 16:09 cat.info Файл: 1 methody methody 69 Ноя 15 16:08 cat.stderr Каталог: 2 methody methody 4096 Ноя 15 12:56 Documents Каталог: 3 methody methody 4096 Ноя 15 13:08 examples Файл: 1 methody methody 83459 Ноя 15 16:11 grep.info Файл: 1 methody methody 26 Ноя 15 13:08 loop Файл: 1 methody methody 23 Ноя 15 13:08 script Файл: 1 methody methody 33 Ноя 15 16:07 textfile Каталог: 2 methody methody 4096 Ноя 15 12:56 tmp Файл: 1 methody methody 32 Ноя 15 13:08 to.sort [methody@localhost methody]$
У sed очень широкие возможности, но довольно непривычный синтаксис, например, замена выполняется командой " s/что_заменять/на_что_заменять/ ". Чтобы в нем разобраться, нужно обязательно прочесть руководство sed(1) и знать
Для того чтобы разобраться в данных, нередко требуется их упорядочить: по алфавиту, по номеру, по количеству употреблений. Основной инструмент для упорядочивания - утилита sort - уже знакома Мефодию. Однако теперь он решил использовать ее в сочетании с несколькими другими утилитами:
[methody@localhost methody]$ cat grep.info | tr "[:upper:]" "[:lower:]" | tr "[:space:][:punct:]" "\n" \ > | sort | uniq -c | sort -nr | head -8 15233 720 the 342 of 251 to 244 a 213 and 180 or 180 is [methody@localhost methody]$
Мефодий (вернее, компьютер по плану Мефодия) подсчитал, сколько раз какие слова были употреблены в файле " grep.info " и вывел несколько самых частоупотребляемых с указанием количества употреблений в файле. Для этого потребовалось сначала заменить все большие буквы маленькими, чтобы не было разных способов написания одного слова, затем заменить все пробелы и знаки препинания концом строки ( \n "), чтобы в каждой строке было ровно по одному слову (Мефодий всюду взял параметры tr в кавычки, чтобы bash не понял их неправильно). Потом список был отсортирован, все повторяющиеся слова заменены одним словом с указанием количества повторений (" uniq -c "), затем строки снова отсортированы по убыванию чисел в начале строки (" sort -nr ") и выведены первые 8 строк (" head -8 ").
Полученные в xargs:
[methody@localhost methody]$ find /bin -type f -perm +a=x \ > | xargs grep -l -e '^#!/' 2> /dev/null /bin/egrep /bin/fgrep /bin/unicode_start /bin/bootanim [methody@localhost methody]$
Здесь Мефодий решил определить, какие из исполняемых файлов в каталоге " /bin " являются -type f " - "обычные файлы" потребовалось, чтобы в результат не попали каталоги, которые обычно являются исполняемыми), а затем для каждого найденного файла вызвал grep, чтобы поискать в нем сочетание #!/ " в начале строки. Ключ " -l " велел grep выводить не обнаруженную строку, а имя файла, в котором найдено совпадение. Так Мефодий получил список исполняемых файлов, в которых есть строка с указанием интерпретатора -
Любая программа - это автомат, предназначенный для обработки данных: получая на входе одну информацию, они в результате работы выдают другую. Хотя входящая и/или выходящая информация может быть и нулевой, т. е. попросту отсутствовать. Те данные, которые передаются программе для обработки - это ее
Каждая программа работает с данными определенного типа: текстовыми, графическими, звуковыми и т. п. Как, наверное, уже стало понятно из предыдущих лекций, основной интерфейс управления системой в Linux - это
"Текстовость" данных - всего лишь договоренность об их формате. Никто не мешает выводить на экран нетекстовый файл, однако пользы в этом будет мало. Во-первых, раз уж файл содержит не текст, то не предполагается, что человек сможет что-либо понять из его содержимого. Во-вторых, если в нетекстовых данных, выводимых на 1528515121, оно представлено в виде четырех байтов: 27, 91, 49 и 74. Соответствующий им текст состоит из четырех esc ", " [ ", " 1 " и " J ", и при ^[[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 . . .
В примере Мефодий, зная заранее, что текста будет выдано много, воспользовался | less ", описанным в разделе " -C " утилита hexdump выводит в правой стороне экрана текстовое представление данных, заменяя непечатные strings "не нашла" в файле /bin/cat явно текстовых подстрок " " и " GNU ": первая из них - вообще не текст (перед ней стоит непечатный 7f, а после - 1 ), а вторая - слишком короткая, хоть и ограничена 0, как это и
полагается строке в скомпилированной программе. Наименьшая длина строки передается strings ключом " -n ".
Для того чтобы записать данные в файл или прочитать их оттуда, процессу необходимо сначала открыть этот файл (при открытии на запись, возможно, придется предварительно создать его). При этом процесс получает дескриптор (описатель) открытого файла - уникальное для этого процесса число, которое он и будет использовать во всех операциях записи. Первый открытый файл получит дескриптор 0, второй - 1 и так далее. Закончив работу с файлом, процесс закрывает его, при этом дескриптор освобождается и может быть использован повторно. Если процесс завершается, не закрыв файлы, за него это делает система. Строго говоря, только в операции открытия дескриптора указывается, какой именно файл будет задействован. В качестве "файла" используются и обычные файлы, и
Каждый процесс Linux получает при старте три "файла", открытых для него системой. Первый из них (дескриптор 0 ) открыт на чтение, это стандартный 1 ) - открыт на запись, это 2 ) предназначается для 3.
Дескриптор - это описатель потока данных, открытого процессом. Дескрипторы нумеруются, начиная с 0. При открытии нового потока данных его дескриптор получает наименьший из неиспользуемых в этот момент номеров. Три заранее открытых дескриптора - стандартный 0 ), 1 ) и 2 ) - выдаются при запуске.
Механизм копирования tty ): пользователь вводит команды с клавиатуры и видит сообщения на экране. Следовательно, любая команда, запускаемая из командной оболочки, будет выводить на тот же
Мефодий уже сталкивался с тем, что некоторые программы умеют выводить не только на info при указании -o " с именем файла выведет текст руководства в файл, вместо того, чтобы отображать его на мониторе. Даже если разработчиками программы не предусмотрен такой ключ, Мефодию известен и другой способ сохранить > " и указать после него имя файла. Таким образом Мефодий уже создавал короткие текстовые файлы ( cat (см. лекцию 5):
[methody@localhost methody]$ cat > textfile Это файл для примеров. ^D [methody@localhost methody]$ ls -l textfile -rw-r--r-- 1 methody methody 23 Ноя 15 16:06 textfile
От использования > " возможности самой утилиты cat, конечно, не расширились. Более того, cat в этом примере не получила от командной оболочки никаких параметров: ни знака " > ", ни последующего имени файла. В этом случае cat работала как обычно, не зная (и даже не интересуясь!), куда попадут выведенные данные: на экран монитора, в файл или куда-нибудь еще. Вместо того, чтобы самой обеспечивать доставку cat отправляет все данные на stdout ).
Подмена > ", и дескриптор этого файла передается программе cat под номером 1 ( fork() появляется два одинаковых процесса, один из которых - дочерний - должен запустить вместо себя команду (выполнить exec() ). Так вот, перед этим он закрывает стандартный вывод (дескриптор 1 освобождается) и открывает файл (с ним связывается первый свободный дескриптор, т. е. 1 ), а запускаемой команде ничего знать и не надо: ее textfile, потребуется другая операция - " >> ":
[methody@localhost methody]$ cat >> textfile Пример 1. ^D [methody@localhost methody]$ cat textfile Это файл для примеров. Пример 1. [methody@localhost methody]$
Мефодий получил именно тот результат, который ему требовался: добавил в конец уже существующего файла данные со
Аналогичным образом для передачи данных на вход программе может быть использован < " служит для перенаправления содержимого файла на sort без параметра, она будет читать строки со sort < имя_файла " подаст на sort данные из файла:
[methody@localhost methody]$ sort < textfile Пример 1. Это файл для примеров. [methody@localhost methody]$
Результат действия этой команды аналогичен команде sort textfile - разница лишь в том, что когда используется " < ", sort получает данные со textfile ", откуда они поступают. Механизм работы shell в данном случае тот же, что и при перенаправлении textfile ", запускает утилиту sort и передает ей на
Необходимо помнить, что операция " > " деструктивна: она всегда создает файл нулевой длины. Поэтому для, допустим, сортировки данных в файле надо применять последовательно sort < файл > новый_файл и mv новый_файл файл. Команда вида команда < файл > тот_же_файл просто урежет его до нулевой длины!
В качестве первого примера и упражнения на перенаправление Мефодий решил записать руководство по cat в свой файл cat.info:
[methody@localhost methody]$ info cat > cat.info info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. [methody@localhost methody]$ head -1 cat.info File: coreutils.info, Node: cat invocation, Next: tac invocation, Up: Output of entire files [methody@localhost methody]$
Удивленный Мефодий обнаружил, что вопреки его указанию отправляться в файл, две строки, выведенные командой info, все равно проникли на stderr ).
Использование 2> ":
[methody@localhost methody]$ info cat > cat.info 2> cat.stderr [methody@localhost methody]$ cat cat.stderr info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. [methody@localhost methody]$
В этот раз на cat.info, cat.stderr. Вместо " > " и " 2> " Мефодий мог бы написать " 1> " и " 2> ". Цифры в данном случае обозначают номера дескрипторов открываемых файлов. Если некая утилита ожидает получить открытый дескриптор с номером, допустим, 4, то, для того чтобы ее запустить, обязательно потребуется использовать сочетание " 4> ".
Иногда, однако, требуется объединить bash для этого имеется специальная последовательность " 2>1 ". Это означает "направить
[methody@localhost methody]$ info cat > cat.info 2>1 [methody@localhost methody]$ head -3 cat.info info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. File: coreutils.info, Node: cat invocation, Next: tac invocation, Up: Output of entire files [methody@localhost methody]$
В этом примере важен порядок перенаправлений: в командной строке Мефодий сначала указал, куда перенаправить > cat.info ") и только потом велел направить туда же 2>1 > cat.info "), результат получился бы неожиданный: в файл попал бы только 2>1 " номер " - это номер открытого дескриптора. Если бы упомянутая выше утилита, записывающая в четвертый дескриптор, была написана на shell, в ней бы использовались перенаправления вида " >4 ". Чтобы не набирать громоздкую конструкцию " > файл 2>1 " в bash используются сокращения: " > файл " или, что то же самое, " > файл ".
Иногда заведомо известно, что какие-то данные, выведенные программой, не понадобятся. Например, предупреждения со /dev/null. Все, что записывается в этот файл, просто будет выброшено и нигде не сохранится:
[methody@localhost methody]$ info cat > cat.info 2> /dev/null [methody@localhost methody]$
Точно таким же образом можно избавиться и от /dev/null.
В bash для перенаправления | ". Самый простой и наиболее распространенный случай, когда требуется использовать less ), которая позволит не торопясь пролистать весь текст, вернуться к началу и т. п.:
[methody@localhost methody]$ cat cat.info | less
Можно последовательно обработать данные несколькими разными программами, перенаправляя cmd1 | cmd2 | ... | cmdN ", которые могут показаться громоздкими и неудобными, но оказываются очень полезными и эффективными при обработке большого количества информации, как мы увидим далее в этой лекции.
Организация
cat: собственно, никакой "фильтрации" данных она не производит, она просто копирует
Данные, проходящие через
В любом дистрибутиве Linux присутствует набор стандартных утилит, предназначенных для работы с файловой системой и обработки текстовых данных. Многими из них Мефодий уже успел воспользоваться: это who, cat, ls, pwd, cp, chmod, id, sort и др. Мефодий уже успел заметить, что каждая из этих утилит предназначена для исполнения какой-то одной операции над файлами или текстом:
Принцип комбинирования элементарных операций для выполнения сложных задач унаследован Linux от операционной системы UNIX (как и многие другие принципы). Подавляющее большинство утилит UNIX не потеряли своего значения и в Linux. Все они ориентированы на работу с данными в текстовой форме, многие являются coreutils.
Работу в системе Linux почти всегда можно представить как работу с текстами. Поиск файлов и других объектов системы - это получение от
Работая с текстом в Linux, нужно принимать во внимание, что текстовые данные, передаваемые в системе, структурированы. Большинство утилит обрабатывает не непрерывный поток текста, а последовательность единиц. В текстовых данных в Linux выделяются следующие структурные единицы:
Строка - основная единица передачи текста в Linux. sort сортирует строки. Строки разделяются \n " (newline).
В одной строке может упоминаться и больше одного объекта. Если понимать объект как последовательность /home/methody " / ", то первое home ", третье - " methody ". Некоторые утилиты позволяют выбирать из строк отдельные
Минимальная единица текста -
^J " - "перевод строки", однако в других кодировках он может быть иным. Кроме того, на большинстве ^M "). Это вызвало путаницу: некоторые системы требуют, чтобы в конце текстового файла стояли оба этих символа в определенном порядке. Чтобы избежать путаницы, в UNIX (и, как следствие, в Linux) было принято единственно верное решение: содержимое файла соответствует кодировке, а при
В распоряжении пользователя Linux есть ряд утилит, выполняющих элементарные операции с единицами текста: поиск, замену, разделение и объединение строк,
Этот раздел посвящен нескольким примерам использования стандартных утилит для решения разных типичных (и не очень) задач. Примеры не следует воспринимать как исчерпывающий список возможностей, они приведены просто для демонстрации того, как можно организовать обработку данных при помощи
В европейской культуре очень большим авторитетом пользуются точные числа и количественные оценки. Поэтому пользователю часто бывает любопытно и даже необходимо точно посчитать что-нибудь многочисленное. Компьютер как нельзя лучше подходит для такой процедуры. Стандартная утилита для подсчета строк, слов и wc (от англ. "word count" - "подсчет слов"). Мефодий запомнил, что в Linux многое можно представить как слова и строки, и решил таким образом посчитать свои файлы:
[methody@localhost methody]$ find . | wc -l 42 [methody@localhost methody]$
Мефодий получил желаемое число - " 42 ". Для этого ему потребовалась команда find - рекомендованный Гуревичем инструмент поиска нужных файлов в системе. Мефодий вызвал find с одним параметром - каталогом, с которого надо начинать поиск. find выводит список найденных файлов по одному на строку, а поскольку критерии поиска в данном случае не уточнялись, то find просто вывела список всех файлов во всех подкаталогах текущего каталога (домашнего каталога Мефодия). Этот список Мефодий передал утилите wc, попросив ее посчитать количество полученных строк " -l ". В ответ wc выдала искомое число.
Задав find критерии поиска, можно посчитать и что-нибудь менее тривиальное, например, файлы, которые создавались или были изменены в определенный промежуток времени, файлы с определенным режимом доступа, с определенным именем и т. п. Узнать обо всех возможностях поиска при помощи find и подсчета при помощи wc можно из руководств по этим программам.
Иногда пользователя интересует только часть из тех данных, которые собирается выводить программа. Мефодий уже пользовался утилитой head, которая нужна, чтобы вывести только первые несколько строк файла. Не менее полезна утилита tail (англ. "хвост"), выводящая только последние строки файла. Если же пользователя интересует только определенная часть каждой строки файла - поможет утилита cut.
Допустим, Мефодию потребовалось получить список всех файлов и подкаталогов в " /etc ", которые принадлежат группе " adm ". И при этом ему почему-то нужно, чтобы найденные файлы в списке были представлены не полным путем, а только именем файла (скорее всего, это требуется для последующей автоматической обработки полученного списка):
[methody@localhost methody]$ find /etc -maxdepth 1 -group adm 2> /dev/null \ > | cut -d / -f 3 syslog.conf anacrontab [methody@localhost methody]$
Если команда получается такой длинной, что ее неудобно набирать в одну строку, можно разбить ее на несколько строк, не передавая системе: для этого в том месте, где нужно продолжить набор со следующей строки, достаточно поставить \ " и нажать Enter. При этом в начале строки bash выведет > ", означающий,
что команда еще не передана системе и PS2 ", описанной в лекции 8.
Мефодий получил нужный результат, задав параметры find - каталог, где нужно искать и параметр поиска - наибольшую допустимую глубину вложенности и группу, которой должны принадлежать найденные файлы. Ненужные /dev/null, а потом указал утилите cut, что в полученных со / " и вывести только третье etc " - содержимое второго
Зачастую пользователю нужно найти только упоминания чего-то конкретного среди данных, выводимых утилитой. Обычно эта задача сводится к поиску строк, в которых встречается определенное слово или комбинация grep. grep может искать строку в файлах, а может работать как bash, которые выполняются в системе:
[methody@susanin methody]$ ps aux | grep bash methody 3459 0.0 3.0 2524 1636 tty2 S 14:30 0:00 -bash methody 3734 0.0 1.1 1644 612 tty2 S 14:50 0:00 grep bash
Первый аргумент команды grep - та строка, которую нужно искать в bash ", а поскольку ps выводит сведения по строке на каждый процесс, Мефодий получил только процессы, в имени которых есть " bash ". Однако Мефодий неожиданно нашел больше, чем искал: в списке выполняющихся процессов присутствовали две строки, в которых встретилось слово " bash ", т. е. два процесса: один - искомый - командный интерпретатор bash, а другой - процесс поиска строки " grep bash ", запущенный Мефодием после ps. Это произошло потому, что после разбора командной строки bash запустил оба дочерних процесса, чтобы организовать ps процесс grep bash уже был запущен и тоже попал в ps. Чтобы в этом примере получить правильный результат, Мефодию следовало бы добавить в | grep -v grep, эта команда исключит из конечного grep ".
Очень часто точно не известно, какую именно комбинацию info, принят такой формат ссылок: " *Note название_узла::". В этом случае нужно искать не конкретное сочетание *Note ", за которой следует название узла (одно или несколько слов и пробелов), оканчивающееся ::"". Компьютер вполне способен выполнить такой запрос, если его сформулировать на строгом и понятном ему языке, например, на языке
[methody@susanin methody]$ info grep > grep.info 2> /dev/null [methody@susanin methody]$ grep -no "\*Note[^:]*::" grep.info 324:*Note Grep Programs:: 684:*Note Invoking:: [methody@susanin methody]$
Первый параметр grep, который взят в кавычки - это и есть info, второй параметр - имя файла, в котором нужно искать. Ключ " -o " заставляет grep выводить строку не целиком, а только ту часть, которая совпала с -n " - выводить номер строки, в которой встретилось данное совпадение.
В Note " и " ::" в Note " и " ::" в тексте. Однако некоторые * "), поставленная после элемента \ ".
Вторая звездочка обозначает, что стоящий перед ней элемент может быть повторен любое количество раз от нуля до бесконечности. В нашем случае звездочка относится к выражению в квадратных скобках - " :"". Целиком .* ") в случае, когда, например, в одной строке встречается две ссылки, вбирает подстроку от
конца первого " :", поместившиеся внутри этой подстроки, распознаются как "любые").
На языке + "), начало и конец строки (" ^ " и " $ " соответственно) и т. д. Благодаря regex(7). Однако руководство - это не учебник, поэтому чтобы научиться экономить время и усилия при помощи
grep. Очень многие программы, так или иначе работающие с текстом, в первую очередь текстовые редакторы, поддерживают
В заключение можно сказать, что
Удобство работы с потоком не в последнюю очередь состоит в том, что можно не только выборочно передавать результаты работы программ, но и автоматически заменять один текст другим прямо в потоке.
Для замены одних tr (сокращение от англ. "translate" - "преобразовывать, переводить"), работающая как
[methody@localhost methody]$ cat cat.info | tr abcdefghijklmnopqrstuvwxyz абцдефгхийклмнопкрстуввсиз \ > | tr ABCDEFGHIJKLMNOPRSTUVWXYZ АБЦДЕФГХИЙКЛМНОПКРСТУВВСИЗ | head -4 Филе: цореутилс.инфо, Ноде: цат инвоцатион, Нест: тац инвоцатион, Тп: Оутпут оф ентире филес 'цат': Цонцатенате анд врите филес =================================== [methody@localhost methody]$
Мефодий потрудился, составляя два параметра для утилиты tr: соответствия латинских букв кириллическим. Первый tr заменяет первым tr дважды: сначала чтобы заменить строчные буквы, а затем - прописные. Он мог бы сделать это и за один проход (просто добавив к параметрам прописные после строчных), но не захотел выписывать столь длинные строки. Полученному на выходе тексту вряд ли можно найти практическое применение, однако транслитерацию можно употребить и с пользой. Если не указать tr второго параметра, то все tr можно также удалить дублирующиеся
Помимо простой замены отдельных sed (сокращение от англ. "
Например, Мефодий с помощью sed может сделать более понятным для непривычного читателя список файлов, выводимый ls:
[methody@localhost methody]$ ls -l | sed s/^-[-rwx]*/Файл:/ | sed s/^d[-rwx]*/Каталог:/ итого 124 Файл: 1 methody methody 2693 Ноя 15 16:09 cat.info Файл: 1 methody methody 69 Ноя 15 16:08 cat.stderr Каталог: 2 methody methody 4096 Ноя 15 12:56 Documents Каталог: 3 methody methody 4096 Ноя 15 13:08 examples Файл: 1 methody methody 83459 Ноя 15 16:11 grep.info Файл: 1 methody methody 26 Ноя 15 13:08 loop Файл: 1 methody methody 23 Ноя 15 13:08 script Файл: 1 methody methody 33 Ноя 15 16:07 textfile Каталог: 2 methody methody 4096 Ноя 15 12:56 tmp Файл: 1 methody methody 32 Ноя 15 13:08 to.sort [methody@localhost methody]$
У sed очень широкие возможности, но довольно непривычный синтаксис, например, замена выполняется командой " s/что_заменять/на_что_заменять/ ". Чтобы в нем разобраться, нужно обязательно прочесть руководство sed(1) и знать
Для того чтобы разобраться в данных, нередко требуется их упорядочить: по алфавиту, по номеру, по количеству употреблений. Основной инструмент для упорядочивания - утилита sort - уже знакома Мефодию. Однако теперь он решил использовать ее в сочетании с несколькими другими утилитами:
[methody@localhost methody]$ cat grep.info | tr "[:upper:]" "[:lower:]" | tr "[:space:][:punct:]" "\n" \ > | sort | uniq -c | sort -nr | head -8 15233 720 the 342 of 251 to 244 a 213 and 180 or 180 is [methody@localhost methody]$
Мефодий (вернее, компьютер по плану Мефодия) подсчитал, сколько раз какие слова были употреблены в файле " grep.info " и вывел несколько самых частоупотребляемых с указанием количества употреблений в файле. Для этого потребовалось сначала заменить все большие буквы маленькими, чтобы не было разных способов написания одного слова, затем заменить все пробелы и знаки препинания концом строки ( \n "), чтобы в каждой строке было ровно по одному слову (Мефодий всюду взял параметры tr в кавычки, чтобы bash не понял их неправильно). Потом список был отсортирован, все повторяющиеся слова заменены одним словом с указанием количества повторений (" uniq -c "), затем строки снова отсортированы по убыванию чисел в начале строки (" sort -nr ") и выведены первые 8 строк (" head -8 ").
Полученные в xargs:
[methody@localhost methody]$ find /bin -type f -perm +a=x \ > | xargs grep -l -e '^#!/' 2> /dev/null /bin/egrep /bin/fgrep /bin/unicode_start /bin/bootanim [methody@localhost methody]$
Здесь Мефодий решил определить, какие из исполняемых файлов в каталоге " /bin " являются -type f " - "обычные файлы" потребовалось, чтобы в результат не попали каталоги, которые обычно являются исполняемыми), а затем для каждого найденного файла вызвал grep, чтобы поискать в нем сочетание #!/ " в начале строки. Ключ " -l " велел grep выводить не обнаруженную строку, а имя файла, в котором найдено совпадение. Так Мефодий получил список исполняемых файлов, в которых есть строка с указанием интерпретатора -
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.