+++ title = "Введение в Linux и Bash, часть III" date = 2019-01-11T08:23:00Z +++ Новый год, новый пост. В данной, третьей и последней, части этого туториала, будут несколько команд и программ которые являются стандартной частью большинства дистрибутивов Линукса. Больше всего внимания я буду выделять программ, которые манипулируют вывод текст других программ и файлов. Также в этом посте мы поговорим о регулярных выражений (коротко - regex, от английского Regular Expression), очень мощный инструмент для поиска текста ## Фильтры Программы, которые манипулируют потоки текста и возвращают его в стандартный вывод, часто зовут фильтрами. Скорее всего вы уже знакомы с первой командой, о которой я будут писать. ### cat Данная команда позволяет посмотреть содержимое текстового файла (или файлов). Название программы ни как не связанна с котейками, а происходит от слово конкатенация. Самое простое применение данной программы - просмотр текстовых файлов. Просто пишите cat а затем путь файла. Однако, как можно предположить исходя из названии программы, она также позволяет соединять несколько текстовых файлов или потоков в один. Например ```sh user@host:~/Documents/notes$ cat sample.txt Pepe cool Tide Pods lame Uganda Knuckles cool Thanos cool JPEG ok Despacito lame Bowsette cool Harold cool Sans coolest Minions lamest NPC cool ``` А теперь допустим что мы хотим соединить соджержимое данного файла с файлом 'sample2.txt' ```sh user@host:~/Documents/notes$ cat sample.txt sample2.txt Pepe cool Tide Pods lame Uganda Knuckles cool Thanos cool JPEG ok Despacito lame Bowsette cool Harold cool Sans coolest Minions lamest NPC cool Troll Face old Can haz chezburger really old ROFLcopter super old Dancing baby ancient ``` Как обычно, у данной команды есть несколько параметров, как например параметр -n чтобы показать номер строки ```sh user@host:~/Documents/notes$ cat -n sample.txt 1 Pepe cool 2 Tide Pods lame 3 Uganda Knuckles cool 4 Thanos cool 5 JPEG ok 6 Despacito lame 7 Bowsette cool 8 Harold cool 9 Sans coolest 10 Minions lamest 11 NPC cool ``` И как я уже рассказывал в предыдущей части, вы можете узнать больше о команде, используя программу man ('man cat'). ### head Данная команда довольно простая, она показывает первые n строки текстового файла/потока. Введите head, затем -n и количество строк вы желаете увидеть, а затем петь файла. Например, допустим что мы хотим увидеть первые 5 строк ```sh user@host:~/Documents/notes$ head -n 5 sample.txt Pepe cool Tide Pods lame Uganda Knuckles cool Thanos cool JPEG ok ``` Если мы не передаем количетсво строк, по умолчанию она выводит первые 10 строк. Для просто напишите head а затем путь файла. ### tail Работает также как head, но в отличие от нее, данная команда показывает последние строки текста. Допустим мы хотим увидеть последние три строки ```sh user@host:~/Documents/notes$ tail -n 3 sample.txt Sans coolest Minions lamest NPC cool ``` Также как и с предыдущей командой, по умолчанию выводятся 10 строк. ### sort С данной командой все очень просто. Она сортирует текст. Например ```sh user@host:~/Documents/notes$ sort sample.txt Bowsette cool Despacito lame Harold cool JPEG ok Minions lamest NPC cool Pepe cool Sans coolest Thanos cool Tide Pods lame Uganda Knuckles cool ``` ### sed sed довольная мощная утилита которая позволяет манипулировать и модифицировать текст. Однако, в данном туториале я не буду углубляться в подробностях работы с программой, но покажу пару пару самых используемых команд. Для работы с данной программой, необходимо передать своего рода скрирта (sed script), который укажет программе что делать с текстом. Первый и самый простой способ использовать sed, это использовать его в качестве программы head, то есть, получить первые b строк текста. Например, допустим что нам необходимо получить первые 7 строк из файла sample.txt ```sh user@host:~/Documents/notes$ sed '7q' sample.txt Pepe cool Tide Pods lame Uganda Knuckles cool Thanos cool JPEG ok Despacito lame Bowsette cool ``` А если более подробно объяснить что данная команда делает, то она говорит программе чтобы она вывела 7 строк, и затем вышла (q). Другой случай, и сокрее всего самое распространенное применение данной команды, это операция поиска и замены текста. Основная синтаксис данной операции выгладит следующим образцом - 's/<поиск>/<замена>/'. По умолчанию данная команда заменяет только первое совпадение в каждой строке, тем не менее мы может указать какие и сколько совпадении мы хотим заменить. Например, если мы добавим двойку в конце команды ('s///2') она заменит только вторые совпадения в каждой строке. Но а что если мы хотим заменить все совпадения во всех строках? Все очень просто - достаточно добавить букву g в конец. Допустим что мы хотим заменить все подстроки "cool" на "dank" в файле sample.txt ```sh user@host:~/Documents/notes$ sed 's/cool/dank/g' sample.txt Pepe dank Tide Pods lame Uganda Knuckles dank Thanos dank JPEG ok Despacito lame Bowsette dank Harold dank Sans dankest Minions lamest NPC dank ``` Обратите внимание на то что команду которую мы передаем sed'у находится в кавычках. Конечно это только одни из самых основных применении. ### grep Это последняя программа-фильтр, о которой я расскажу. Я покажу самое основное применение данной программы, а затем, после того как расскажу о регулярных выражений, покажу ее более интересные применения. grep - программа, которая выполняет поиск выражения переданный ей пользователем, и выводит на экран строки, совпадавшие с условиями поиска. Допустим, например, что мы хотим увидеть только крутые (cool) мемы ```sh user@host:~/Documents/notes$ grep 'cool' sample.txt Pepe cool Uganda Knuckles cool Thanos coolcharacter Bowsette cool Harold cool Sans coolest NPC cool ``` То, что мы передали grep'у является самым простым видом регулярного выражения. По факту мы указали программе чтобы нам показала строки где содержится подстрока "cool". ## Регулярные выражения Регулярное выражение - язык поиска и манипуляции подстроками в тексте. Для поиска используется строка текста, часто называемая строка-образец или "шаблон", состоящая из символов, которые задают правило поиска. Регулярные выражения применяются в многих программах и языках программирования, таких как например редакторов текста и поисков, и естественно, может быть довольно полезным в терминале. ### Антракт Перед тем как объяснить как работать с регулярными выражениями, хочу показать пару символов, облегчающие жизнь при работе с файлами в терминале - символы-джокеры (на англ. wildcards). В терминале они - звездочка (*) и вопросительный знак (?). Как раз из-за их специального применения, их нельзя использовать в названиях файлов. Начнем со звездочки. Звездочка озночает что на ее месте может быть любое количество любых символов. Например, чтобы искать файлы, чье название начинается с sa ```sh user@host:~/Documents/notes$ ls sa* saturday.txt sample.txt sample2.txt sample.png ``` Другой пример, найти файлы чье название просто содержит подстроку sa ```sh user@host:~/Documents/notes$ ls *sa* asado.png saturday.txt sample.txt sample2.txt sample.png ``` Вопросительный знак указывает на то что, на его месте должен быть символ, любой символ. Допустим что, мы хотим посмотреть все файлы которые называются sample, у которых есть трех-символьное расширение ```sh user@host:~/Documents/notes$ ls sample.??? sample.txt sample.png ``` Символы-джокеры очень полезные когда необходимо манипулировать несколько файлов с похожими названиями. Однако, если названия файлов не похоже никак, нам придется использовать фигурные скобки, чтобы указать список файлов. Например ```sh user@host:~/Documents/notes$ rm {monday.txt,december1999.txt,saturday.txt} ``` ### Обратно к regex А теперь я объясню основные части и символы регулярных выражении, а затем вам покажу как их использовать в grep * `.` - Точка означает один символ (любой символ). Например, 'be.r' найдет нам bear, beer, befr, и т.д. * `*` - Предыдущий элемент совпадает 0 или больше раз. Например 'an*t' нам найдет at, ant, annt, annnt, и т.д. * `+` - Предыдущий элемент совпадает один или больше раз. Например 'an+t' нам найдет ant, annt, annt, и т.д. * `?` - Предыдущий элемент совпадает 0 или один раз. Например 'an?t' нам найдет at и ant. * `{n}` - Предыдущий элемент совпадает ровно n раз. * `{min, }` - Предыдущий элемент совпадает хотя бы min раз * `{min, max}` - Предыдущий элемент совпадает хотя бы min раз и не больше max раз. * `|` - Логический оператор ИЛИ. Например, 'gray|grey' нам найдет gray и grey. * `()` - Круглые скобки группируют несколько символов в один элемент. Например 'gr(a|e)y' нам найдет gray и grey. * `[abc]` - Совпадает если один из символов, который внутри скобок, присуствует. * `[^abc]` - Совпадает если нет ни одного, из которых внутри скобок. * `[a-d]` - Диапазон символов. То есть a, b, c и/или d. * `^` - Начало строки. * `$` - Конец строки. А теперь, ради примера с grep, допустим что, мы хотим найти все строки в которых содержится "cool" или "ok" в них. В этом случае нам нужна вертикальная черта "|". Однако, если использовать grep без параметров, нам нужно будет напечатать слеш перед ней "\|". Поэтому лучше использовать команду egrep, которая является сокращением "grep -E", затем чтобы включить расширенные регулярные выражения. Например ```sh user@host:~/Documents/notes$ egrep 'cool|ok' sample.txt Pepe cool Uganda Knuckles cool Thanos cool JPEG ok Bowsette cool Harold cool Sans coolest NPC cool ``` А теперь допустим что, нам неоюходимо найти все строки с буквой 't' в качестве последнего символа в строке ```sh user@host:~/Documents/notes$ egrep 't$' sample.txt Sans coolest Minions lamest ``` Я уже продемонстрировал применение regex'ов с grep'ом (и/или egrep). А теперь я хочу вам показать более практический пример с sed'ом. Да, в sed'e помимо собственного языка, можно еще и регулярные выражения использовать. Допустим у нас есть файл который выглядит следующим образом ```sh user@host:~/Documents/notes$ cat shortcuts # Some shortcuts d ~/Documents D ~/Downloads m ~/Music pp ~/Pictures vv ~/Videos s ~/.scripts # My scripts cf ~/.config # My configs ``` Как вы могли заметить, в нашем файле много пустых строк, и много комментарри, которые полезные для человека, но бесполезные для компьютера. Начнем с того что, удалим комментарии, для этого мы будем использовать команду sed'а для поиска и замены, только в нашем случае мы хотим заменить комментарии на пустоту. Затем нам понадобится вставить регулярное выражение, которое поможет нам найти комментарии - '#.*'. Этот шаблон переводится как - найди символ '#' и все что после него находится. А теперь давайте мы все совместим ```sh user@host:~/Documents/notes$ sed 's/#.*//g' shortcuts d ~/Documents D ~/Downloads m ~/Music pp ~/Pictures vv ~/Videos s ~/.scripts cf ~/.config ``` Вот и мы избавились от комментариев. Тем не менее нам еще осталось избавится от пустых строк, и если вы заметили, комментарии были удалены, но перед некоторыми из них остались пробелы. И так, давайте мы сначала улучшим нашу команду, для этого нам нужно найти там где есть 0 или больше пробелов перед комментарии, но как нам обозначит пробелы в sed'е? Все очень просто с '\s', таким образом наша команда а теперь выглядет вот так 's/\s*#.*//g'. А теперь нам нужно избавится от пустых строк. Для этого нам нужно ввести еще одну команду sed'а, но мы можем ее ввести вместе с предыдущей командой отделяя их точкой и запетой (;). Нам осталось придумать как найти пустую строку, все очень просто - '^$', то есть, найти ту строку где ее начало и ее конец находятся вместе. Нам осталось указать sed чтобы он удалил эту строку, и вот я вам расскажу еще одну команду sed - команду для удаления (d), и так... ```sh user@host:~/Documents/notes$ sed 's/\s*#.*//g; /^$/d' shortcuts d ~/Documents D ~/Downloads m ~/Music pp ~/Pictures vv ~/Videos s ~/.scripts cf ~/.config ``` Конечно, когда мы вводим эту команду, она не переписывает файл, она всего лишь выводит на экран результат операции. Если вам необходимо переписать исходный файл вы можете передать sed параметр '-i. ### Конвейер и перенаправление Последнее о чем я буду писать в этом туториале не команда и не программа, но очень полезная вещь, которая есть во всех Unix и Unix-подобных системах - конвейер. Конвейер - это цепочка перенаправляющая вывод процесса или процессов в стандартный ввод других процессов. В том числе есть и операторы которые позволяют перенаправлять вывод программы в файл и наоборот. ### Перенаправление в и из файлов Допустим что мы хотим повторить последний пример, но в этот раз мы хотим записать результат в файл. Мы уже знаем как переписать оригинальный файл, но в этот раз мы хотим записать результат в новый файл. Для этого нам понадобятся операторы перенаправления Unix'а '>' и '>>'. Первый оператор переписывает файл, если указанный файл уже существует, а второй просто добавляет поток текста в конец файла. В этом случае безразлично какой из этих операторов использовать, ибо мы хотим записать поток текста на новый файл ```sh user@host:~/Documents/notes$ sed 's/\s*#.*//g; /^$/d' shortcuts > shortcuts_clean ``` Так же существует оператор перенаправления ИЗ файла в стандартный ввод программы - '<'. Однако, в большинство случаях достаточно передать путь файла в качестве аргумента. ### Конвейер А теперь я вам покажу как перенаправить вывод одной программы в другую. Чтобы перенаправить вывод из одной программы в другую, достаточно ввести команду первой программы, затем ввести вертикальную черту (|), а затем команду второй программы. Допустим мы хотим увидит первые три файлы в нашей директории, для этого мы можем направить вывод ls в head, вот так ```sh user@host:~/Documents/notes$ ls | head -n 3 asado.png monday.txt sample.txt ``` А теперь вернемся к файлу sample.txt. Допустим что сначала мы хотим отсортировать все строки файла, и хотим оставить только те строки с "cool" и "lame". Затем, мы хотим заменить неправильные старые термины, на современные, то есть "cool" на "dank" и "lame" на "normie". И наконец, мы хотим это сохранить в файл. И вот как все это выгладит ```sh user@host:~/Documents/notes$ egrep 'cool|lame' sample.txt | sort | sed 's/cool/dank/g;s/lame/normie/g' > memes.txt ``` Взглядываем в файл и... ```sh user@host:~/Documents/notes$ cat memes.txt Bowsette dank Despacito normie Harold dank Minions normiest NPC dank Pepe dank Sans dankest Thanos dank Tide Pods normie Uganda Knuckles dank ``` И вот и все ## Post scriptum Перед тем как закончить с этим туториалом, я хочу вам показать еще несколько программ, которые могут вам пригодится ### less Данная команда вам пригодится когда, например, некоторая программа выводит слишком много текста. В таком случае, достаточно перенаправить вывод текста первой программы к less используя оператор конвейера (|), также как я вам только что показал. Используя эту команду вы можете листать текст используя стрелочки или vim-клавиши (hjkl). Так же вы можете искать термины введя слеш (/). ### tar Это de facto официальная программа Линукса для архивирования и сжатия файлов в формате .tar. Чаще всего используется формат сжатия gunzip (.gz), но есть и другие форматы сжатия. Есть два основных способов использовать эту программу. Первый чтобы разархивировать ```sh user@host:~/Documents/notes$ tar -xzvf oldnotes.tar.gz ``` Второй чтобы архивировать и сжать ```sh user@host:~/Documents/notes$ tar -czvf allnotes.tar.gz * ``` Как обычно, вы можете узнать больше об этой программе используя утилиту man ('man tar'). ### ssh and scp Скорее всего вы уже слышали или даже работали с ssh, даже если вы не работали до этого с Ликусом или Unix/Unix-подобных системах. Это программа позволяет подключится через терминал к другим компьютером через сеть (например, интернет), в том числе и к серверам. Допустим вы хотите подключится к серверу с ip 180.80.8.20 и пользователь tux ```sh user@host:~$ ssh tux@180.80.8.20 ``` Здесь мы предполагаем что мы подключаемся через стандартный порт ssh (22), иначе придется его передать используя параметр -p а затем номер порта. А теперь поговорим о scp. Это программа позволяет передать файлы из одного компьютера в другого используя протокол ssh'а. Допустим что мы хотим отправить файл с локального компьютер в тот же самый сервер, что и в прошлом примере ```sh user@host:~$ scp somefile tux@180.80.8.20:/home/tux/directory/ ``` Если бы мы хотели наоборот, получить, а не отправить, то мы просто поменяли порядок аргументов, примерно вот так ```sh user@host:~$ scp tux@180.80.8.20:/home/tux/directory/somefile directory/ ``` Так же как и с ssh порт по умолчанию 22, то есть если использовать другой порт, нужно его указать, только в отличие от ssh, параметр -P вместо -p и нужно его ввести сразу после "scp. Вот и на этом все. Надеюсь вам этот туториал помог. С наступившим 2019.