Reference book of shell

Оглавление страницы:

Ввод и вывод данных в интерпретаторе shell

echo

Перенаправление ввода-вывода

Стандартный поток ввода — stdin

Стандартный поток вывода — stdout

Стандартный поток ошибок — stderr

Файловый ввод-вывод

Основные операторы переадресации:

Переадресация потоков

Переадресация стандартного потока вывода

Переадресация стандартного потока ввода. "Документ здесь '<<' "

Переадресация стандартного потока ошибок

Переадресация обоих выходных потоков

Объединение выходных потоков в файле

Файловые дескрипторы

Резюмируя перенаправление ввода/вывода можно сказать так:

Подстановка имен файлов

Применение метасимвола '*'

Применение метасимвола '?'

Применение метасимволов […] и [!…]

read

cat

Строковый редактор ed

VI - текстовой редактор операционной системы

Pipe

tee

exec

Применение дескрипторов файлов

Порядок выполнения команд

Оператор &

Оператор &&

Оператор ||

Группирование команд с помощью скобок

{xxx,yyy,zzz,...} -- Фигурные скобки

(команда1; команда2;...) -- круглые скобки:

Регулярные выражения

Создание шаблонов для поиска выражений

Поиск одиночных символов с помощью метасимвола ´.´

Поиск выражений в начале строки с помощью метасимвола ¨^¨

Поиск выражений в конце строки с помощью метасимвола ¨$¨

Поиск символов, встречающихся неопределенное число раз, с помощью метасимвола "*"

Поиск специальных символов с помощью метасимвола ¨\¨

Поиск символов, входящих в заданный набор или диапазон ¨[ ]¨

Поиск символов встречающихся заданное число раз

Command line is a text interface for your computer.

http://aosabook.org/en/bash.html 

http://mywiki.wooledge.org/BashParser

https://runebook.dev/ru/docs/BashManual 

https://housecomputer.ru/bash_guide  

LINUX_От_понимания_к_применению  PDF

Bash MAN  <----читать постоянно, читать на ночь, лучше на английском

Bash MAN GNU.org 

Advanced Bash-Scripting Guide <----------

Токен (token) — «знак, символ; опознавательный знак; жетон» объект, создающийся из лексемы (распознанные группы) в процессе лексического анализа токенизации (tokenizing).

Шаблон токена — формальное описание класса лексем, которые могут создать данный тип токена

Лексема (слово, примитив, token) — последовательность допустимых символов языка программирования, имеющая смысл для транслятора который выполняет  преобразование "исходного языка"  в язык "объектный" имеющий смысл для работы конкретной машины.

Лексический анализ («токенизация») — процесс аналитического разбора входной последовательности символов на распознанные группы — лексемы — с целью получения на выходе идентифицированных последовательностей, называемых «токенами» (подобно группировке букв в словах).

Синтаксический анализ (разбор или парсинг parsing) в лингвистике и информатике — процесс сопоставления линейной последовательности лексем (слов, токенов) естественного или формального языка с его формальной грамматикой. Результатом является дерево разбора (синтаксическое дерево). Обычно применяется совместно с лексическим анализом.

Синтаксический анализатор (парсер parser) — это программа или часть программы, выполняющая синтаксический анализ

Нисходящий парсер (top-down parser), восходящий парсер (bottom-up parser), область применения всё что угодно, имеющее синтаксис («составление», «координация», «порядок») например предложения и словосочетания, целью синтаксисов является установление синтаксических правил, синтаксис команды echo: echo [ПАРАМЕТР]... [СТРОКА]...

 Синтаксические единицы и примитивы


Примитивы, то есть "базовый" тип данных, предоставляемый языком программирования как базовая встроенная единица языка, статичная и не изменяемая(что не относится к объектно орентированным языкам, где есть возможность добавлять к этим типам новые операции, и изменять старые), они же лексемы (token) - минимальная единица языка, имеющая самостоятельный смысл.

В bash есть три основных типа токенов: зарезервированные слова (или ключевые), слова и операторы. (Слово —  упорялоченная последовательность символов, слова —  любые последовательности символов между пробелами)

$ echo I love bash terminal                 —   пять слов

$ echo -e "\033[36m I love bash terminal"   —   три слова

$ ....Строка разбивается на слова точно так же, как и при чтении команды, поэтому несколько слов, разделенных метасимволами и взятые в кавычки, считаются одним словом, такое слово называется string. Процесс установки кавычек называется quoting (quote 'цитировать', 'ссылаться', она же "маскировка"). Кавычки удаляются, прежде чем слово передается другой программе (см. ниже).


Ключевые слова — это те, которые имеют значение для оболочки и ее языка, что значит имеют значение?, то есть инициируют конструкции управления потоками, например, такие как if, while, function, их не мало, скобки ([[  ]]), то же ключевое слово  и т.д, идентификаторы то есть уникальные признаки объекта с такими именами запрещены.

Операторы состоят из одного или нескольких метасимволов: символов-джокеров, которые сами по себе имеют особое значение для оболочки, например | и >

Остальная часть ввода оболочки состоит из обычных слов, некоторые из которых имеют особое значение например, операторы присваивания или числа в зависимости от того, где они появляются в  командной строке

*** Понятия определяющая часть "парадигмы", одни и те же понятия используются в различных контекстах, используя контекст мы локализуем и понятия, так "слово, лексема. токен",  в контексте Bash можно считать одно и тоже, в контексте языка С понятия будет расходиться.

Переменные и параметры

Как и в любом языке программирования, оболочки предоставляют переменные: переменные это имена для обозначения сохраненных данных и работы с ними. Оболочка предоставляет основные устанавливаемые пользователем переменные и некоторые встроенные переменные, называемые параметрами (в контексте оболочки). Параметры оболочки обычно отражают некоторые аспекты  состояния оболочки и устанавливаются автоматически при старте или как побочный эффект другой операции.

Значения переменных - это строки. Переменные присваиваются с помощью операторов формы name=value. Value не является обязательным; его пропускание присваивает пустую строку, "пустая строка " это то же переменная в итоге name=   будет равно "пустая строка" и подобная переменна часто используется. Если значение указано, оболочка расширяет значение и присваивает его name. Оболочка может выполнять различные операции в зависимости от того, установлена ли переменная или нет, но присвоение значения это единственный способ установить переменную. Как проверить является ли переменная пустой, не установленной:

$ var=

$ if [ -n "$var" ]; then echo "not empty"; else echo "empty"; fi

empty

$ var=1

$ if [ -n "$var" ]; then echo "not empty"; else echo "empty"; fi

not empty

$

Или так:

$ var=

$ if [ "x$var" = "x" ]; then echo "empty"; else echo "not empty"; fi

empty

$ var=1

$ if [ "x$var" = "x" ]; then echo "empty"; else echo "not empty"; fi

not empty

Переменные, которым не было присвоено значение, даже если они были объявлены и получили атрибуты, называются неустановленными . 

Слово, начинающееся со знака доллара, обозначает ссылку на переменную или параметр. ($var ссылка)

Слово, включая знак доллара, заменяется значением названной переменной. (var=1 переменная и ее значение)

Оболочка предоставляет богатый набор операторов раскрытия, от простой замены значения до изменения или удаления частей значения переменной, соответствующих шаблону..

Bash использует хэш-таблицы для хранения и извлечения переменных оболочки и связанные списки этих хеш-таблиц для реализации области видимости переменных. Существуют разные области видимости переменных для вызовов функций оболочки и временные области для переменных, устанавливаемых операторами присваивания, предшествующими команде. Например, когда эти операторы присваивания предшествуют команде, встроенной в оболочку, оболочка должна отслеживать правильный порядок разрешения ссылок на переменные, а связанные области позволяют это делать с помощью bash. В зависимости от уровня вложенности выполнения может потребоваться большое количество областей 

действия.


Парсинг

Parse анализировать, parser анализатор или "синтаксический анализатор". Первоначальной задачей механизма синтаксического анализа является лексический анализ: разделить поток символов на слова и применить значение к результату. 

Слово это основная единица, на которой работает синтаксический анализатор. Слова это последовательности символов, разделенных метасимволами, которые включают простые 

разделители, такие как пробелы и табуляторы, или символы, которые являются специальными для языка оболочки, например точки с запятой и амперсанды.

Лексический анализатор берет строки ввода из строки чтения или другого источника, разбивает их на токены по метасимволам, идентифицирует токены на основе контекста и передает их синтаксическому анализатору для сборки в операторы и команды и здесь задействовано много контекста - например, слово for может быть зарезервированным  словом, идентификатором, частью оператора присваивания или другим словом.

Bash позволяет заменять первое слово простой команды произвольным текстом или псевдонимом (alias). Поскольку они полностью лексичны, то есть способны становиться частью языка, лексемы без ущерба для синтаксиса, псевдонимы можно использовать для изменения грамматики оболочки: например можно написать псевдоним реализующий составную команду, которую оболочка bash не предоставляет, с использованием псевдонимов создаются сложные и эффективные конструкции. Синтаксический анализатор bash полностью реализует псевдонимы на лексической фазе, НО синтаксический анализатор должен знать, когда расширение псевдонима разрешено, одним из примеров может послужит применение "ключевого слова" function перед именем функции. где ключевое(зарезервированное) слово function используется для предотвращения "столкновений" псевдонимов оболочки (alias) с именем функции (с ключевым словом function псевдоним не раскрывается):

.


В каком порядке "Bash parser" экранирует символы и разбивает слова/токены в командной строке? 

(согласно статье: http://mywiki.wooledge.org/BashParser)


    Группировки команд и расширения скобок, например {…}.

    Процессные замены, например cmd1 < (cmd2).

    Перенаправление.

    Каналы.

    Расширение скобки, например {1..3}

    Расширение тильды, например ~root .

    Расширение параметра, например ${var##*/}. или ${parameter: -word} - раскроет до параметра и слова.

    Арифметическое разложение, например $((1+12)).

    Подстановка команд, например $(date).

    Расщепление слов, которое применяется к результатам расширений; использует $IFS - разделитель полей во вводимой строке (IFS -- Input Field Separator) по умолчанию  пробел.

    Расширение пути или глобирование, например ls ?d*.

Ввод и вывод данных в интерпретаторе shell

Команды и сценарии могут получать входные данные двумя способами: из стандартного входного потока (связан с клавиатурой - stdin(Ø)) или из файла. Аналогичное разделение существует и при выводе данных: результаты работы команды или сценария по умолчанию направляются на экран терминала, но можно перенаправить их в файл. 

Если в процессе работы возникают ошибки, сообщения о них тоже отображаются на экране. Ошибки это интересно, это познавательно, это путь приводящий к успеху, но не для всех и всегда это очевидно, чтобы избежать вывода ошибок в терминале, можно перенаправить поток ошибок в файл:  $ command > outfile 2>&1   или в помойку: 2>/dev/null

"Успех — это умение двигаться от одной неудачи к другой не теряя энтузиазма"

echo

http://www.opennet.ru/man

Из названия не трудно догадаться чем занимается эта команда, делает она "отражение, вывод на печать" своих аргументов, echo команда не "системная" (если не учитывать echo-повтор) то есть не имеющая исполняемого файла это внутренняя команда интерпретаторов и как любой язык интерпретатор должен иметь возможност выполнить команду print

Общий ее формат таков:

 echo [ПАРАМЕТР]... [СТРОКА]..

    -n не выводить в конце символ новой строки (без ключа новая строка создается автоматически)

    -e включить интерпретацию управляющих символов, перечисленных ниже

    -E отключить интерпретацию управляющих символов в строках

Это все опции команды, если воспользоваться ключом -e, то появляется возможность использования  Escape (управляющих) последовательностей, что бы вставлять специальные символы, или для того что бы их обрабатывал скрипт (#!/bin/sh -e), управляющие символы по умолчанию не распознаются:

\\           обратный слэш

\a           тревога (BEL)

\b           забой

\c           подавлять символ новой строки в конце

\f           перевод страницы

\n          новая строка

\r           возврат каретки

\t           горизонтальаня табуляция

\v          вертикальаня табуляция 

Например "новая строка":

~$ echo -e "$PWD \n$LANG \n$SHELL \nend"

/home/user 

en_US.UTF-8 

/bin/bash 

end

~$

Например "горизонтальная табуляция":

~$ echo -e "$PWD \t$LANG \t$SHELL \tend"

/home/user en_US.UTF-8 /bin/bash end

~$ 

Например "вертикальная табуляция":

~$ echo -e "$PWD \v$LANG \v$SHELL \vend"

/home/user 

           en_US.UTF-8 

                       /bin/bash 

                                 end

~$ 

Например "возврат каретки" (удалить все символы до начала строки):

~$ echo -e "$PWD \r$LANG $SHELL end"

en_US.UTF-8 /bin/bash end

~$ 

Например "подавит символ новой строки":

~$ echo -e "$PWD $LANG $SHELL \c"

/home/user en_US.UTF-8 /bin/bash ~$

Что будет равно:

$ echo -n "$PWD $LANG $SHELL "

/home/user en_US.UTF-8 /bin/bash ~$ 

Как и всевозможные комбинации:

~$ echo -e "$PWD \r$LANG \t$SHELL \tend"

en_US.UTF-8 /bin/bash end

~$ 

Создать файл с неким содержанием, дописать в файл:

echo "ru_RU.UTF-8 UTF-8">/etc/locale.gen

echo "en_US.UTF-8 UTF-8">>/etc/locale.gen

#locale-gen

#dpkg-reconfigure locales

Просто распечатать:

$ echo $LANG

ru_RU.UTF-8

$

Распечатать содержимое текущей папки:

~$ echo *

Распечатать файлы определенного расширения:

~$ echo *.txt

******  Примеры использования регулярных выражений совместно с командой echo разнообразны и многочисленны.

Добавить поддержку русских шрифтов для консоли

#dpkg-reconfigure console-cyrillic

(если нет  #apt-get install console-cyrillic)

Все по умолчанию, а Do you want to setup Cyrillic on the console at boot-time? ставим Yes

https://proadminz.ru/lokalizatsiya-debian/

------------------------------------

Одной из проблем, с которыми часто сталкиваются пользователи при работе с командой echo, является включение в строку двойных кавычек. Символы двойных кавычек имеют специальное назначение в интерпретаторе shell, поэтому должны быть защищены при пори помощи обратного слеша. Вот как выводится на экран строка "/dev/rmt0":

~$ echo "\"dev/rmt0"\"

"dev/rmt0"

В конце концов вывод echo можно раскрасить.

Цвета текста:

\033[30m - чёрный;

\033[31m - красный;

\033[32m - зелёный;

\033[33m - желтый;

\033[34m - синий;

\033[35m - фиолетовый;

\033[36m - голубой;

\033[37m - серый.

Цвета фона:

\033[40m - чёрный;

\033[41m - красный;

\033[42m - зелёный;

\033[43m - желтый;

\033[44m - синий;

\033[45m - фиолетовый;

\033[46m - голубой;

\033[47m - серый;

\033[0m - сбросить все до значений по умолчанию.


В конце концов есть аналог echo - printf: https://aidalinux.ru/Printf 

~$ echo -e "\033[36m$PWD \033[31m\v$LANG \033[32m \v$SHELL \033[33m\vend"

/home/user 

           en_US.UTF-8  

                        /bin/bash 

                                      end

~$ echo -e "\033[46m$PWD \033[41m\v$LANG \033[42m \v$SHELL \033[43m\vend"

/home/user 

           en_US.UTF-8  

                        /bin/bash 

                                      end



$ printf '%b\n' 'Типа echo'

Типа echo

Например применяя стиль к некой строке, мы можем использовать команду:

echo -e '\033[1mYOUR_STRING\033[0m'   Где:

echo -e означает, что экранированные строки (\) будут интерпретироваться

\033 экранированная последовательность начало/конец стиля

lowercase m указывает на конец последовательности

1 атрибут bold шрифта (см. справа)

[0m сбрасывает все атрибуты

$ echo -e '\033[1mYOUR_STRING\033[0m'

YOUR_STRING

Возможные значения:

0 - Normal Style

1 - Bold

2 - Dim

3 - Italic

4 - Underlined

5 - Blinking

7 - Reverse

8 - Invisibl

PS: Кроме того echo одна из функций операционной системы эхо-повтор. Без него невозможно увидеть набираемый нами текст. echo обеспечивает, то  что каждый поступающий с терминала  символ сразу же копируется и отсылается обратно. Только в этом случае можно видеть осуществляемый вами ввод непосредственно на мониторе. Во время опроса паролей функция эхо-повтора, естественно, отключается, более подробно надо рассматривать утилиту stty.

ls — Listing

Еще одна базовая команда, это чистой воды утилита, в Linux дистрибютивах как правило привязанная к псевдониму ls:

$ type ls

ls is aliased to `/bin/ls -hFh --color'

За долгую историю своего существования обросла массой ключей, позволяющих применять ее где угодно и с большой гибкостью, ниже только часть ее опций:

-a отображать все файлы, включая скрытые

-A не отображать ссылку на текущую папку и корневую папку

--author - выводить создателя файла в режиме подробного списка;

-b выводить Escape последовательности вместо непечатаемых символов;

--block-size выводить размер каталога или файла в определенной единице измерения, например, мегабайтах, гигабайтах или килобайтах;

-B не выводить резервные копии, (имена начинаются с тильды);

-c сортировать файлы по времени модификации или создания, сначала будут выведены новые файлы;

-C выводить колонками;

--color включить цветной режим вывода;

-d выводить только директории, без их содержимого;

-D использовать режим вывода, совместимый с Emacs;

-f не сортировать;

-F показывать тип объекта, к каждому объекту будет добавлен один из специализированных символов */=>@|;

--full-time показывать подробную информацию, плюс вся информация о времени в формате ISO;

-g показывать подробную информацию, но кроме владельца файла;

--group-directories-first сначала отображать директории, а уже потом файлы;

-G не выводить имена групп;

-h — выводить размеры папок в удобном для чтения формате;

-H — открывать символические ссылки при рекурсивном использовании;

--hide — не отображать файлы, которые начинаются с указанного символа;

-i — отображать номер индекса inode, в которой хранится этот файл;

-l — выводить подробный список, в котором будет отображаться владелец, группа, дата создания, размер и другие параметры;

-L — для символических ссылок отображать информацию о файле, на который они ссылаются;

-m — разделять элементы списка запятой;

-n — выводить UID и GID вместо имени и группы пользователя;

-N — выводить имена как есть, не обрабатывать контролирующие последовательности;

-Q — брать имена папок и файлов в кавычки;

-r — обратный порядок сортировки;

-R — рекурсивно отображать содержимое поддиректорий;

-s — выводить размер файла в блоках;

-S — сортировать по размеру, сначала большие;

-t — сортировать по времени последней модификации;

-u — сортировать по времени последнего доступа;

-U — не сортировать;

-X — сортировать по алфавиту;

-Z — отображать информацию о расширениях SELinux;

-1 — отображать один файл на одну строку.

Примеры приводить бессмысленно, поскольку их великое множество, если конечно ей пользоваться а не пользаваться mc, mc это "дурной тон", наглядность структуры файловой системы в итоге формируется в голове пользователя и потребность любоваться ей в двух панельном варианте рано или позно отпадет, но конечно скажут, что там удобны операции копирования, удаления, макрокоманды .....люди! все это суета, то что называется "игра не стоит свечь", Unix самодостаточная операционная система в своей основе и не требует или почти не требует дополнительного софта для администрирования, в заключении все таки надо привести пример, пример использования позиционных параметров командной строки, ну о подсветке файлов и говорить не стоит, плюс привязка к псевдонимам, и в итоге все не менее одобно, плюс команды past, split, fold и тд:

$ ls ~/common ~/copier / . ..

.:

 apparmor/               Documents/            lp               typescript

 base/                   Downloads/            lxc-rest/        vertical-overview/

 blacklist.txt           eco                   Mail/            Videos/

 common/                 emptydir/             Makefile.in      VMware/

 conky.html              file1                 Music/           vmware-host-modules/

 conky_kill*             GNS3/                 myapp_postgre/   VMware-Workstation-Full-16.0.0/

 conkyrc                 grepp.txt             Pictures/       'Без имени 1.odg'

 conkyrc_main            HP/                   Public/          Видео/

 copier/                 hplip-3.21.12/        scan/            Документы/

 COPYING                 installer/            skb-0.4/         Загрузки/

 copyright*              link@                 Telegram/        Изображения/

'created direct vcvcv'   loganalyzer-4.1.11/   Templates/      'Рабочий стол'/

 Desktop/                logclean*             topten


..:

user/


/:

 0      'data portainer'/   ifpwd*            lib/          mnt/    root/   sys/   vmlinuz@

 bin/    dev/               ifwright*         lib64/        opt/    run/    tmp/   vmlinuz.old@

 boot/   etc/               initrd.img@       lost+found/   path/   sbin/   usr/

 Data/   home/              initrd.img.old@   media/        proc/   srv/    var/


/home/user/common:

utils.c  utils.h


/home/user/copier:

copier.py  __init__.py

$ ....Использование команды ls совместно с циклом for

ls права в восьмеричном формате:

$ ls -l | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf("%0o ",k);print}' 

$ ls -l conkyrc | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf("%0o ",k);print}'

644 -rw-r--r-- 1 user user 2.2K Nov 26 17:44 conkyrc

Перенаправление ввода-вывода

http://www.gnu.org/bash/manual/Redirections.html

http://xgu.ru/wiki/Стандартные потоки ввода/вывода 

Возможно надо сказать, что вычеслительную технику удобнее рассматривать в концепции "потоков", а вычислительные комплексы в концепции "сети" регулирующей обмен этими потоками, потоками данных и потоками команд, тот взгляд которого придерживается "Sun Microsystems", безусловный авторитет в области "computer science", и с этой точки зрения возможность управлять, перенаправлять потоки центральный инструмент, как и понятие, определяющий "философию" UNIX. 

С каждым процессом (командой, сценарием и т.п.), выполняемым в интерпрепторе shell, как и процессом как таковым, связан ряд открытых файлов, из которых процесс может читать свои данный, и в которые он может записывать их. Каждый из этих файлов идентифицируется числом, называемым дескриптором файла (файловым дескриптором), о чем желательно всегда помнить но у первых трех файлов есть также имена которые легче запоминать:

Встроенные файловые дескрипторы: Ø (stdin), 1 (stdout), 2 (stderr).


В действительности создается 12 открытых файлов, файлы с дескрипторами Ø,1,2 резервируются для стандартных потоков ввода, вывода и ошибок. Пользователи могут также работать с файлами, имеющими дескрипторы от 3 до 9.     $ ls -lah /proc/$(echo $$)/fd/

Стандартный поток ввода — stdin

Файл стандартного потока ввода (stdin) имеет дескриптор Ø. Из этого файла процессы извлекают свои входные данные. По умолчанию входной поток ассоциирован с клавиатурой (устройство /dev/tty), но чаще всего он поступает по каналу (pipe | ) от других процессов или из обычного файла

Стандартный поток вывода — stdout

Файл стандартного потока вывода (stdout) имеет дескриптор 1. В этот файл записываются все выходные данные процесса. По умолчанию данные выводятся на экран терминала (устройство /dev/tty), но их можно также перенаправить в файл или послать по каналу другому процессу

Стандартный поток ошибок — stderr

Файл стандартного потока ошибок (stderr) имеет дескриптор 2. В этот файл записываются сообщения об ошибках, возникающих в ходе выполнения команды. По умолчанию сообщения об ошибках выводятся на экран терминала (устройство /dev/tty), но их также можно перенаправить в файл. Зачем же для регистрации ошибок выделять специальный файл? Дело в том, что это очень удобный способ выделения из результатов работы команды собственно выходных данных, а также хорошая возможность эффективно организовать ведение различного рода журнальных файлов.

Для операций с этими дескрипторами, существуют специальные символы: > (перенаправление вывода), < (перенаправление ввода). 

Символ & предваряет номер дескриптора; например, 2>&1 — перенаправление дескриптора 2 (stderr) в дескриптор 1 (stdout).

Файловый ввод-вывод

При вызове команд можно указывать, откуда следует принимать входные данные и куда необходимо направлять выходные данные, а также сообщения об ошибках. По умолчанию, если не указано иное, подразумевается работа с терминалом: данные вводятся с клавиатуры и выводятся на экран. Интерпретатор располагает механизмом переадресации, позволяющим ассоциировать стандартные потоки с различными файлами. Во время перенаправления стандартного потока ошибок следует указывать дескриптор файла &2. ****Для потоков ввода и вывода делать это не обязательно.

command &> outfile перенаправление выводов stdout и stderr команды в файл outfile

command >&2 перенаправление вывода stdout команды в поток stderr 

Основные операторы переадресации:

Наименьшую автономную часть языка программирования (команда или набор команд, но не примитивы), принято именовать statement, не очень удачный перевод на русский будет соответствовать "оператор" или "инструкция", не удачный поскольку операция, оператор это не что иное чем "statement", что обычно утверждение, заявление. Операторов переадресации не много;                >, &>, >&, >>, <   ....., собственно и все, стоит отметить запись типа &> как и >&, то есть если мы не указали дескриптор файла, то подразумевается  потоки stdout и stderr, вот на всякий случай страница справочного руководства:

Redirecting Standard Output and Standard Error

      This  construct allows both the standard output (file descriptor 1) and

      the standard error output (file descriptor 2) to be redirected  to  the

      file whose name is the expansion of word.


      There  are  two  formats  for  redirecting standard output and standard

      error:


             &>word

      and

             >&word


      Of the two forms, the first is preferred.  This is semantically equivalent to


             >word 2>&1

Ниже несколько часто опотребляемых примеров перенаправления потоков, потоки и их перенаправление, то есть возможность ими манипулировать "ключевой" можно сказать "фундаментальный" аспект Unix. https://www.gnu.org/software/bash/manual/Redirections.html 

Переадресация стандартного потока вывода

Что бы проилюстрировать переадресацию стандартного потока вывода воспользуемся — AWK (www.opennet-awk sed_awk IBM-awk) — интерпретируемый скриптовый  C-подобный язык построчного разбора и обработки входного потока (например, текстового файла) по заданным шаблонам (регулярным выражениям).

В следующей командной строке из файла /etc/passwd извлекаются имена пользователей, известных в системе, полученный список сортируется по алфавиту, а результаты направляются в файл sort.out: 

$ cat /etc/passwd | awk -F: '{print $1}' | sort > sort.out

Опция - F программы awk свидетельствует о том, что указанный после нее символ двоеточия является разделителем полей в файле /etc/passwd.

Результат — > файл sort.out:

$ cat sort.out

avahi

avahi-autoipd

backup

bin

colord

daemon

.......

fetchmail

games

imint

irc

kernoops

libuuid

list

lp

mail

........

news

nobody

.........

root

rtkit

saned

speech-dispatcher

.........

usbmux

uucp

www-data

Группировка команд:

В один и тот же файл в режиме присоединения можно направлять результаты работы сразу нескольких команд:

$ ls -l /etc/ssh | grep ^d >> files.out; ls /etc/conky >> files.out

или: $ ls -l /etc/ssh | grep ^d >> files.out && ls /etc/conky >> files.out

$ cat files.out

drwxr-xr-x 2 root root 4.0K Feb 26  2020 ssh_config.d/

drwxr-xr-x 2 root root 4.0K Feb 26  2020 sshd_config.d/

conky.conf

conky_no_x11.conf

$

....или так: 

$ { ls -l /etc/ssh | grep ^d && ls /etc/conky; } > files.out

$ cat files.out

drwxr-xr-x 2 root root 4.0K Feb 26  2020 ssh_config.d/

drwxr-xr-x 2 root root 4.0K Feb 26  2020 sshd_config.d/

conky.conf

conky_no_x11.conf

$   Следует помнить применяя "логическое 'И' - &&", что следующая команда после первой будет выполнена лишь в случае "успеха" первой, ";" - после последней команды обязательно

В первой части  файла files.out помещается список каталогов /etc/ssh, а во второй, список файлов /etc/conky.

Для создания пустого файла нулевой длины выполните следующую команду: $ > myfile


Удалить файл в текущем рабочем каталоге: $ rm [файл] [Enter]

Чтобы удалить каталог со всеми подкаталогами и файлами в нем, используйте опцию `-R' (recursive): $ rm -R [каталог] [Enter]

Чтобы удалить пустой каталог, используйте команду rmdir; она удаляет каталог, указанный в качестве аргумента. Если Вы укажете каталог, в котором есть файлы или подкаталоги, rmdir сообщит об ошибке: $ rmdir [пустой каталог] [Enter]


Группировка команд:

Различие между ними состоит в том, что первый разделяет дочерний процесс создавая subshell, а второй работает в контексте основной  оболочки не изменяя переменные окружения. 

( ) - групировка команд  { } - блок кода (функция), cat в первом примере занимается соединением (cat - concatenate).

Закрывающая скобка в группировании команд (и функций) должна быть отделена от содержимого точкой с запятой или новой строкой, потому, что "}"на самом деле это отдельная команда (ключевое слово), и должна рассматриваться как одна.

Переадресация стандартного потока ввода. Документ здесь '<<'  "heredoc"

Интерпретатор встретив в командной строке оператор "<<". наченает воспринимать данные вводимые с клавиатуры как входной поток в указанный файл или команду, пока в следующей строке не будет введено "слово-разделитель" указанное после оператора, "слово-разделитель" это любое слово в том числе и "EOF - end of file":

$ cat > files.out << eof

> 12345

> 67890

> eof

$ cat files.out

12345

67890

Отличительная деталь операторов переадресации потоков "<<  >>" от операторов "<  >"  в том, что они не перезаписываю, а добавляют данные.

Чтобы из командной строки отправить пользователю электронное сообщение, которое находится в файле, следует направить файл программе (например mutt). Посредством следующей команды пользователь test@ya.ru получит сообщение, которое содержится в файле files.out

$ mutt test@ya.ru < files.out

Результат — > mutt:

Более "простой" пример отправка сообщения другому Пользователю через терминал:

$ who

root     tty1         2016-10-07 10:57

idebian  pts/0        2016-10-07 09:35 (192.168.1.101)

поскольку root-у послания запрешены, посылает root:

# write idebian pts/0

Привет!

передать содержимое файла воспользовавшись pipe:

# cat <файл> | write idebian pts/0

или так же без pipe (отослать и выйти из write):

# write idebian pts/0 < <файл>

Переадресация вида (команда << слово-разделитель) называется конструкцией “документ здесь” (heredoc). Встречая в командной строке оператор <<, интерпретатор shell воспринимает все данные, вводимые с клавиатуры, как входной поток, пока в отдельной строке не будет введено слово-разделитель, указанное в командной строке после оператора. Разделителем может служить любое слово. 

https://www.opennet.ru     https://linuxhint.com/bash-heredoc-tutorial. 

Вот как, например, можно создать файл в режиме командной строки:


$ cat >> myfile << Пока

> Привет! Я работаю за терминалом $TERM

> мое имя $LOGNAME

> Пока!

> Пока

$ cat myfile

Привет! Я работаю за терминалом xterm

мое имя imint

Пока

***обычно пишут EOF (end of file)

Строка здесь '<<<'  "here-string"

<<< - это here-string передает строку на ввод команды, все преимущество в том, что используя канал для той же цели мы используе subshells, и с переменными в исходной оболочке естественно будут проблемы например:

$ echo "hello world" | read first

$ echo $first

     #встает законный вопрос: Где переменная?

И совсем другое дело с here-string

$ read first <<< "hello world"

$ echo $first

hello world

В общем и целом here-string это передача строки в stdin:

$ echo <<< echo "Передача строки в stdin"

Передача строки в stdin

$ cat <<< "string"

string

$

 here-string может рассматриваться как урезанная форма here document.

$ cat <<< "Here-String ${USER} ${HOME}"

Here-String user /home/user

$    https://www.baeldung.com/heredoc-herestring 

http://www.bash-scripting.ru/abs/chunks/ch18.html

Переадресация стандартного потока ошибок

При переадресации стандартного потока ошибок указывается дескриптор 2. Рассмотрим пример. Утилита grep ищет в файле missiles строку “trident”:

Однако в текущем каталоге нет такого файла, и соответствующее сообщение об ошибке по умолчанию выводится на экран. Можно переслать все сообщения об ошибках в системную корзину (устройство /dev/null):

После чего никакие сообщения на экране отображаться не будут. Подобный режим работы не всегда желателен. Часто сообщения об ошибках необходимо фиксировать в файле для последующего анализа. В следующей командной строке сообщения об ошибках пересылаются в файл grep.err

Во многих случаях создается общий журнальный файл, в который добавляются сообщения об ошибках, поступающие от многих команд. При этом следует использовать оператор >>, чтобы не перезаписывать файл.

$ grep "trident" missiles

grep: missiles: Нет такого файла или каталога

$

$ grep "trident" missiles 2> /dev/null

$  

$ grep "trident" missiles 2> grep.err

$ cat grep.err

grep: missiles: Нет такого файла или каталога

Удобно пользоваться подсветкой при выводе ошибок:

$ grep user /etc/* 2> >(while read line; do echo -e "\e[01;31m$line\e[0m"; done)

Переадресация обоих выходных потоков


В одной командной строке можно последовательно переадресовывать как стандартный поток вывода, так-и стандартный поток ошибок. Ниже приведен пример, в котором команда cat обрабатывает два файла (myfile и account_end.doc), направляя вывод в файл accounts.out, а сообщения об ошибках — в файл accounts.err

$ cat myfile account_end.doc 1> accounts.out 2> accounts.err

$ cat accounts.out

Привет! Я работаю за терминалом xterm

мое имя imint

Пока

$ cat accounts.err

cat: account_end.doc: Нет такого файла или каталога

$

Объединение выходных потоков в файле

Оператор n>&m позволяет перенаправить файл с дескриптором n, в файл с дескриптором m. Подобных операторов в командной строке может быть несколько, в этом случае они вычисляются справа на лево. Рассмотрим пример: $ cleanup > cleanup.out 2>&1

Здесь сценарий cleanup направляет все свои выходные данные (как поток вывода, так и поток ошибок) в файл cleanup.out. Символ амперсанта перед дескриптором файла, пишется с одной целью, чтобы интерпретатор знал, что речь идет о дескрипторе, файле с дескриптором "1", то есть первая часть команды: cleanup > cleanup.out, направляет stdout в файл, и вторая часть 2>&1: поток stderr, дескриптор    2 (поток ошибок) направляет в поток stdout, дескриптор  1 (поток вывода), итого: вывод в файл, ошибки в вывод (все волшебство в том, что ошибки направляются в вывод которого нет, равно /dev/null).

На первый взгляд "вывод в файл, ошибки в вывод", как минимум не последовательно, однако это часто используемая запись и поэтому лучше на примере: 

Создадим файл "grepp.txt" в домашнем каталоге со строкой 'example' , начнем искать ее по всему каталогу предполагая, что ошибок будет много и перенаправив вывод (stdout) в файл "file1", grep по обыкновению вывел ошибки в stdout и завершил работу, напечатав файл мы увидим результаты его поиска "grep.txt:example", добавив к команде "2>&1" ни каких ошибок в выводе не появится, файл перезапишется с "полезными" и "бесполезными" данными, и в нем grep первым делом сообщит, что: "file1: input file is also the output". 

Конечно можно и "дописывать"; 

$ grep exemple * >> file1 2>&1, ....но более "эстетично" будет так:

$ grep exemple * &> file1 &> перенапправить и перезаписать вывод и ошибки

$ grep exemple * &>> file1 &>> перенаправить и дописать вывод и ошибки

В этом случае амперсанд - & означает как стандартный вывод "1", так и стандартную ошибку "2".

Самым "верным" способом будет отправить ошибки в /dev/null, и амперсант не нужен:

$ grep example * > file1 2>/dev/null

$ cat file1

grepp.txt:example


$ cat > grepp.txt

example

^C

$ grep example * > file1

grep: GNS3: Is a directory

grep: link: Is a directory

grep: loganalyzer-4.1.11: Is a directory

grep: lxc-rest: Is a directory

.....................

$ cat file1

grepp.txt:example

$ grep example * > file1 2>&1

$ cat file1

grep: file1: input file is also the output

grep: GNS3: Is a directory

grepp.txt:example

grep: loganalyzer-4.1.11: Is a directory

grep: lxc-rest: Is a directory

........................


$ grep example * &> file1

$ cat file1

grepp.txt:example

grep: file1: input file is also the output

grep: GNS3: Is a directory

grepp.txt:example

grep: loganalyzer-4.1.11: Is a directory

grep: lxc-rest: Is a directory

.........................

Файловые дескрипторы

Дескриптор (descriptor «описывающий») — лексическая единица (слово, словосочетание) информационно-поискового языка. 

Не следует путать файловые дескрипторы с индексными , если индексные дескрипторы это по сути и есть файлы, системное имя файлов, то есть внутреннее системное имя файла это номер его индексного дескриптора (inumber), хранящего информацию о файле и узнать его можно выполнив команду ls с ключом -i(ls -i), которая покажет иноды, эти самые индексные дескрипторы, а найти файл по номеру инода поможет команда  "find  [путь] [номер инода]", то с файловыми дескрипторами все обстоит более замысловато, хотя и не сложно, дело в том, что фаилового дискриптора не существует до тех пор пока файл не становится связанным с каким нибудь процессом, проще говоря открыт, дескриптор файла -- это число, по которому система идентифицирует открытые файлы, идентифицирует и выполняет с ними текущие или запланированные процессы,  по умолчанию после загрузки система открывает три файла асоциированные с тремя потоками: поток ввода, поток вывода и поток ошибок, естественно это не все файлы открываемые после старта системы, достаточно вспомнить сокеты, которые тоже файлы ....и прочее, порядка 12-ти. Узнать файловый дискриптор задача не столь тривиальная как узнать номер инода, для этого можно воспользоваться командой "lsof - list Open Files": https://linux-notes.org/lsof/ ; https://zalinux.ru ; https://www.opennet.ru/lsof_util ; https://www.ibm/using-file-descriptors , для начала откроем файл;

$ vim file1

И выполнив команду: 

$ lsof | grep file1

COMMAND   PID   TID TASKCMD  USER   FD  TYPE  DEVICE   SIZE/OFF                        NODE NAME

   vim  41521                user   6u  REG      8,7      12288    1090422 /home/user/.file1.swp

..... и в столбце "FD - file descriptor" увидим его номер -6 и символ указывающий на режим в котором файл был открыт - u (файл открыт для чтения и для записи), закрыв vim, увидим пустой вывод команды "lsof | grep file1", пример не "абсолютный" но от части "демонстрирующий". Ниже еще две неплохие статьи на ту же тему;

Как проверить все открытые файлы

Файл дескриптор в Linux с примерами

Файлы это глобальный ресурс. Что бы система могла с ними работать применяется индексация в случае файловых дискрипторов, это процесс в процессе их использования: это целочисленные значения или файловые дескрипторы, результат индексации выполняющейся динамически. Если процесс открывает файл, на этот открытый файл ссылается индекс. Этот индекс уникален для процесса ( но не для потока). Если файл закрыт, дескриптор файла (целочисленный индекс) больше не используется и может быть повторно использован процессом (как и любым из его потоков), или другим процессом. Иноды индексные дескрипторы, тоже результат  индексации, индексации на уровне файловой системы как таковой в отличии от файловых дескрипторов можно условно сказать глобальной индексации.

Что бы понятие "файловый дескриптор" не оставалось пустым звуком наверное надо рассмотреть их практическое участие в работе "операционной системы", на примере взаимодействия двух процессов по средствам системного вызова(говоря проще "функции"), системного вызава - pipe то есть канала ("програмного" - реализующего "однонаправленную" передачу данных), пример более чем банальный и рутинный.

Итак: pipe как системный вызов, то есть ядро, согласно алгоритму своей работы , вернул два файловых дискриптора, два целочисленных числа (согласно таблице, то есть структуры данных содержащей список открытых файлов и список дискрипторов файлов ) fd[0] - для записи в канал и, fd[1] - для чтения из канала, и при условии, что дочерний процесс наследует и разделяет все назначенные файловые дескрипторы родительского, два процесса обмениваются данным, по средствам файловых дескрипторов (в том числе), пример не блестящий для взаимодействия  независимых процессов, но наглядно демонстрирующий зачем вообще нужны файловые дескрипторы, которые можно рассматривать в качестве "оперативных" посредников между процессами и файловой системой, что вполне естественно с точки зрения быстродействия, что бы каждый раз не обращаться к таблице inod-ов, а иметь посредника в "быстрой памяти".

 ulimit -n   (-n the maximum number of open file descriptors;  -a all current limits are reported)

Резюмируя перенаправление ввода/вывода можно сказать так:

В любой unix системе, по умолчанию открыто три файла, ассоциированных через таблицу с целочисленными значениями под названием "файловые дескрипторы":

stdin ( стандартный поток ввода - клавиатура )          дескриптор        Ø

stdout ( стандартный поток вывода - экран )                 дескриптор        1

stderr ( стандартный поток вывода ошибок )                дескриптор        2


Операторы перенаправления позволяют передать вывод из файла, сценария, команды или блока команд на ввод другого файла, сценария, команды. 

Например: 

$ test.sh > outfile             перенаправление вывода сценария stdout(1) в файл outfile

$ command &> outfile    перенаправление выводов stdout(1) и stderr(2) команды в файл outfile, в этом случае & это stdout и stderr

$ command > outfile 2>&1   перенаправление выводов stdout(1) и stderr(2) команды в файл outfile (это копия "&> outfile")

$ command >&2              перенаправление вывода stdout(1) команды в поток stderr(2)

$ N<&-  0<&- закрыть перенаправление ввода, дескриптор 0, или любой другой N

$ test.sh >> outfilen        перенаправление вывода сценария stdout в файл, в режиме добавления в конец файла

$ << heredoc

$ command <<< echo "Передача строки в stdin"     herestring  $ cat <<< "string"

Символ & предваряет номер дескриптора; например, 2>&1 — перенаправление дескриптора 2 (stderr) в дескриптор 1 (stdout).

Символ & - тут нужен для того, чтобы пояснить bash, что вы имеете в виду не файл с именем 1, а именно файл с дескриптором 1

Во время перенаправления стандартного потока вывода ошибок следует указывать дескриптор файла stderr(2). Для потоков ввода (Ø) и вывода (1) делать это не обязательно.

https://www.cyberciti.biz/faq/redirecting-stderr-to-stdout/ <--------- хорошая статья 

https://www.opennet.ru/docs/RUS/bash_scripting_guide/c11620.html

Если взглянуть на это с точки зрения процессов, то можно сказать, что процессы имеют доступ к трем файлам по средствам файловых дискрипторов:

Процессы, запускаемые с терминала, обычно используют терминал вместо всех этих трех файлов, однако, что самое важное и полезное каждый файл независимо от других может быть "перенаправлен". Например: операция подстановки процесса, передает вывод одного процесса на ввод другого:

(command)>

<(command)

между символами <,> и круглой скобкой не должно быть пробела.


Стандартный ввод-вывод основной инструмент сцепления програм (утилит, сценариев), инструмент конструирования программ из менее сложных в более сложные, идея основанная на том, что любая программа в Unix обладает стандартными понятиями, на первый взгляд всем известными, это stdin и stdout, ошибки не в счет, по средствам которых появляется возможность создавать объекты, то есть "локальные" формализованные конструкции, путем манипуляции этими потоками, перенаправлением в том числе, и это основное, позже придуманый pipe позволил сцеплять вход одного на выход другого в чем и заключается можно сказать "концепция" Unix, в итоге достаточно иметь некий програмный минимум в виде ядра и набор утилит, програмных unit-ов (блоков, секций, и тут можно задуматься откуда вообще появилось название "UNIX") из которых будут составлены сложные, практически востребованные программы, и в этом контексте перенаправление stdin и stdout добавляет функциональность и гибкость этим конструкциям, как и вообще использованию Unix. Идея иметь ядро и "нечто" вокруг него оказалась плодотворной, и сейчас мы имеем ядро GNU/Linux  и набор дистрибютивов вокруг его. 

Оболочка собственно инструмент для создания подобных конструкций, дальше больше ..инструменты совершенствуются, появляются AWK - SED и  так далее по экспоненте. В целом медод сцепления  програмных unit-ов в более сложные конструкции в языках высокого уровня позже будет называться "наследованием" целью которого является ерархическое упорядовачиние создоваемых, более сложных объектов. (https://drive.google.com/file/= 53:50 )

Не безинтересно разобраться, что такое вообще "поток", кратко (если это возможно) так:

Поток – это абстрактное понятие, относящееся к любому переносу данных от источника к приемнику, при том что поток определяется как последовательность байтов и не зависит от конкретного устройства, с которым производится обмен (оперативная память, файл на диске, клавиатура,принтер ...). для увеличения скорости передачи данных обмен производится,через специальную область оперативной памяти она же — буфер. Все операции ввода-вывода реализуются с помощью функций, которые находятся в библиотеке С, потоковый ввод-вывод в том числе.

При открыти потока, происходит связывание указателей потока с конкретным файлом, структурой предопределенного типа FILE, определение которой находится в библиотечном файле. В структуру входит: указатель на буфер, указатель на текущую позицию файла и т.д., в результате возвращается указатель на поток, т. е. на объект типа FILE. Более подробно о стандартном вводе выводе:  Роберт Love_Системное программирование  ст.102

Понятие потока важное и фундаментальное понятие и в целом "разумно обобщая" можно сказать, что операционная система только и делает, что работает с потоками.


Подстановка имен файлов

{Метасимвол — Символ-джокер — Символ подстановки} — символ, используемый для замены других символов или их последовательностей, приводя таким образом к символьным шаблонам, результатом развития символов-джокеров являются регулярные выражения, однако метасимволы оболочки и язык регулярных выражений - RegExr, это несколько разные вещи, кроме того метасимволы разных оболочек не обязаны совпадать, поскольку каждая оболочка есть "эксклюзивный" програмный продукт (Цитирование в оболочке Korn (POSIX)). 

Интерпретатор (shell) так же предлагает набор метасимволов, позволяющих находить файлы, имена которых соответствуют предложенному шаблону. 

Вообщем "метасимвол" можно понимать как шаблон, набор "чего либо", греческая приставка "мета" означает абстрагированность, обобщенность, переход к чему-либо другому, перемену состояния, превращение (например: метаданные — данные о данных)

**** Передавая регулярные выражения с метасимволами в виде "аргументов командной строки", следует заключать их в кавычки, чтобы предотвратить попытки командной оболочки выполнить подстановку вместо них.

Ниже список некотрых метасимволов, когда интерпретатор встречает указанные символы в командной строке, он обрабатывает их соответственно их символьному шаблону, при условии, что вы не защитили их с помощью кавычек.

Применение метасимвола '*'

Символ звездочки может служить заменой любой части имени файла. Следующая команда выводит список всех файлов, имена которых начинаются со строки "app":

$ ls app*

appdva app_tapes

appdva_SLA

Вот как можно получить список файлов, имеющих расширение doc:

$ ls *.doc

accounts.doc qtr_end.doc

Представленная ниже команда находит файлы, у которых имя начинается со строки "cl", а расширение равно sed:

$ ls cl*.sed

cleanlogs.sed cleanmeup.sed

cleanmessages.sed

Звездочку удобно применять, когда, например, не хочется вводить полное имя каталога при переходе в него:

$ cd /etc

$ ls -l | grep ^d

drwxr-xr-x 2 root root 1024 Jan 26 14:41 cron.daily

drwxr-xr-x 2 root root 1024 Jan 27 1998 cron.hourly

drwxr-xr-x 2 root root 1024 Jan 27 1998 cron.monthly

drwxr-xr-x 2 root root 1024 Jan 26 14:37 cron.weekly

$ cd cron.w* 

S pwd

/etc/cron.weekly

Применение метасимвола '?'

Знак вопроса служит для замены любого отдельного символа. Следующая команда выводит список файлов, имена которых содержат не менее трех символов, причем третьим является символ 'R':

$ ls ??R*

BAREAD

Следующая команда ищет файлы с именами, начинающимися со строки "conf", за которой следуют два произвольных символа и расширение log:

$ ls conf??.log .

confl2.log conf.2.log

conf25.log

Вот как можно найти файлы, имена которых состоят не менее чем из четырех символов, причем первым является символ 'f', а последним — 's':

$ ls f??*s

ftpaccess ftphosts ftpconversions ftpusers ftpgroups

Применение метасимволов […] и [!…]


Метасимволы [… ] соответствуют любому символу из числа тех, что указаны в квадратных скобках. Представленная ниже команда выводит список файлов, имена которых начинаются с символа 'i' или 'o':

$ ls [io]*

inetd.conf ioctl.save outputrc

info?dir inputrc

initrunlvl issue

inittab issue.net

    В скобках можно задавать диапазон символов. Начальный и конечный символы при этом разделяются дефисом. Например, следующая команда ищет файлы с именем log, в расширении которых первый символ — цифра:

$ ls log.[0-9]*

log.0323 log.0325 log.0324 log.0326

    Метасимволы [!…] соответствуют любому символу из числа тех, что не указаны в квадратных скобках. Если в предыдущем примере на первом месте в скобках поставить восклицательный знак, команда будет искать файлы с именами log, в расширении которых первый символ не является цифрой: 

$ ls log.[!0-9]*

log.sybase

    Приведенная ниже команда ищет файлы, имена которых начинаются со строки "LPS", два следующих символа могут быть произвольными, затем идет символ, не являющийся цифрой, а за ним — произвольная строка:

$ ls LPS??[!0-9]*

LPSILP LPSOSI LPSOPS LPSPOPQTR

    Поиск файлов, имена которых начинаются с символа верхнего регистра, производится посредством такой команды:

$ ls [A-Z]*

    Следующая команда ищет файлы, имена которых, наоборот, начинаются с символа нижнего регистра:

$ 1а [а–z]*

    А эта команда находит файлы, в начале имени которых стоит цифра: 

$ ls [0-9]*

    Вот как можно найти все скрытые файлы (такие как .profile, .rhosts, .history и т. д.): 

$ ls .*

    Метасимволы представляют собой универсальный инструмент поиска строк по шаблону. С их помощью легко находить нужные файлы и каталоги. Далее мы более подробно рассмотрим способы применения метасимволов в составе регулярных выражений.

read

"Замечательная" команда read, это встроенная команда bash, которая считывает строку из стандартного ввода (или из файлового дескриптора), если строка состоит из нескольких слов, разбивает строку на слова, первое слово в качестве значения присваивается первому имени переменной, указанной как аргумент команды, второе — второму и так далее. Если задана единственная переменная, в нее записывается вся строка. Если ввести команду read без параметров строка помешается в переменную среды $REPLY. При указании нескольких переменных в первую из них записывается первое слово строки, во вторую — второе слово и тд., последней переменной присваивается остаток строки. Общий формат команды:    read  переменная1  переменная2...

Иначе так: команда read это способ взаимодействия пользователя с вводом с клавиатуры, который вы можете увидеть как stdin, команда будет ждать, пока пользователь введет данные, которые будут присвоены переменной или переменным, указанным в качестве аргумента, аргументов команды. Стандартно используется в скриптах, когда надо присвоить значение переменной из stdin (например совместно с конструкциями оператора выбора case).

В следующем примере в переменную variable_1 записывается весь вводимый с клавиатуры текст до тех пор, пока не будет нажата клавиша [Enter]:

~$ read variable_1

test_1 variable_1

~$ echo $variable_1

test_1 variable_1

~$

~$ read

переменная REPLY

~$ echo $REPLY

переменная REPLY

~$ 

Представленная ниже команда заносит введенный текст в две переменные. В качестве разделителя между словами используется пробел.

$ read variable_1 variable_2

test_2 variable_2

$ echo $variable_1 $variable_2

test_2 variable_2

$ echo $variable_1

test_2

$ echo $variable_2

variable_2

Если во входной строке больше слов, чем указано переменных, в последнюю переменную записываются все оставшиеся слова:

$ read variable_1 variable_2

test_2 variable_2 test_3 test_4

$ echo $variable_1 $variable_2

test_2 variable_2 test_3 test_4

$ echo $variable_1

test_2

$ echo $variable_2

variable_2 test_3 test_4

cat

https://ru.wikipedia.org/wiki/Cat

http://www.opennet.ru/man

cat - печать файлов, команда cat - concatenate универсальна. Эту команду удобно применять как для отображения файла, так и для его создания, а также при отображении файлов, содержащих управляющие символы. Используя команду cat, следует учитывать, что процесс вывода не останавливается по достижении конца зкрана терминала — файл пролистывается  до конца, о чем, не совсем явно,  говорит ее название concatenate - соединять, это одно из востребованных свойств, когда есть задача объеденить несколько файлов

Масса вариантов применения команды cat, в том числе и тех которые возникают в процессе ее использования, например скопировать файл используя перенаправление: cat > file1 file2 в результате будет создана копия файла file2 под именем file1 (естественно существцет команда cp специально для этого предназначенная)

$ cat > file2

ggggg

gggggj

^C

$ cat > file1 file2

$ cat file1

ggggg

gggggj


На этом "нетривиальном" примере легко понять суть утилиты: concatenate - соединять, Первым делом перенаправление создает файл file1, далее "соединяет" с файлом file2, который не пустой, в результате происходит "копирование"(если можно так сказать), если бы файл file1 был не пустой то был бы перезаписан, если бы оператором перенаправления были бы две стрелки >>, то был бы дописан, все в полном соответствии с операторами перенаправления потоков, можно добавить что подобными "хитростями" языки оболочек изобилуют и "пытливый юзер" не будет скучать.


Если необходимо просмотреть файл постранично, надо либо использовать, либо передать вывод команды cat какой-нибудь программе постраничной разбивки more, less ...:

$ cat textfile | more   или    $ cat textfile | pg   или   $ cat textfile | less

Общий формат команды cat таков:

cat  [опции]  имя_файла1. . .  имя_файла2. . .

Из опций команды cat в первую очередь заслуживает внимания опция -v, активизирующая режим отображения непечатаемых символов.

$ cat textfile1 textfile2 textfile3 >> bigfile

Кроме того, существует понятие фильтра. Фильтром является программа, которая читает данные из стандартного ввода, некоторым образом их обрабатывает и результат направляет на стандартный вывод, можно сказат фильтры это стандартные команды (овеянные "духом древности"), команды которые могут быть применены без использования каналов (каналы появились только с "третьей редакции UNIX"), например: find, tee, tr, grep, sort, cut ......, надо учитывать, что понятия, термины формируются и живут в "процессе", так и понятие "фильтр" с появлением каналов потеряло былую актуальность. 

Когда применяется перенаправление, в качестве стандартного ввода и вывода могут выступать файлы, по умолчанию, stdin и stdout, программа cat — пример простейшего фильтра, она ничего не делает с входными данными, а просто пересылает их на выход.

**** Если необходимо создать новый файл можно использовать: перенаправление (>) и ввести в него текст; дописать существующий применив перенаправление (>>) и  ввести текст; 

воспользоваться оператором "here document (<<)" и ввести текст;  для нумерации строк есть ключ -n:

$ ~ cat > textfile

text text test

vvvvvvvvvvvvvv

xxxxxxxxxxxxxx

^C

$ ~ cat textfile

text text test

vvvvvvvvvvvvvv

xxxxxxxxxxxxxx

$ ~ cat >> textfile

дополнение

#пустая строка

^C

$ ~ cat textfile

text text test

vvvvvvvvvvvvvv

xxxxxxxxxxxxxx

дополнение

$ ~ cat -n textfile

     1  text text test

     2  vvvvvvvvvvvvvv

     3  xxxxxxxxxxxxxx

     4  дополнение

     5

$ ~

В данном случае cat читает данные не из файла, а из стандартного входного потока (клавиатуры), и перенаправляет его в новый файл. По завершении ввода данных нажмите 

[Ctrl+D (C)], нумерация строк "интерактивна" и в файл не записывается. Для просмотра управляющих символов в файле воспользуйтесь опцией -v. 

Или просто создать файл:

$ cat > file1

Enter          #пустая строка, либо необходимый текст

CTRL+D         #выход

$ ls -l f_desc --time=atime

-rw-r--r-- 1 user user 93 Dec 27 18:16 f_desc  

время последнего изменениям данных

$ ls -l f_desc --time=ctime

-rw-r--r-- 1 user user 93 Dec 27 18:16 f_desc  

время последнего изменения метаданных

$ ls -l f_desc --time=birth

-rw-r--r-- 1 user user 93 Dec 24 14:20 f_desc  

время создания 

Другое дело когда требуется создать несколько файлов, и тут перенаправление работать не будет, понадобиться touch, подстановка оптимизирует задачу:

$ touch file1 file2 file3

используя подстановку

$ touch file{1,2,3}

$ ls file*

file1  file2  file3

или так

$ touch files{1..5}

$ ls files*

files1  files2  files3  files4  files5

PS: Файл естественно можно создать и без cat, простым перенаправлением: 

$ > file1 С таким же успехом файл можно создать с помощью любого текстового редактора, если орентироваться на интернет, user-ам от чего то для этой цели нравится использовать команду touch, однако у нее есть более интересное применение, это установка и изменение временных меток файла, то есть метаданных файла, то есть возможность непосредственно редактировать свойства inode -да, например возьмем файл "f_desc":

$ ls -l f_desc --time=atime

-rw-r--r-- 1 user user 93 Dec 24 14:20 f_desc

изменим метку, с помощью ключа на текущее время:

$ touch -a f_desc

$ ls -l f_desc --time=atime

-rw-r--r-- 1 user user 93 Dec 27 18:16 f_desc

$ stat f_desc

  File: f_desc

  Size: 93      Blocks: 8      IO Block: 4096   regular file

Device: 807h/2055d Inode: 1170272     Links: 1

Access: (0644/-rw-r--r--) Uid: ( 1000/ user)   Gid: ( 1000/ user)

Access: 2021-12-27 18:16:00.121013519 +0300

Modify: 2021-12-24 14:20:30.583667664 +0300

Change: 2021-12-27 18:16:00.121013519 +0300

 Birth: 2021-12-24 14:20:18.183668124 +0300

$ https://omgubuntu.ru/ispolzovaniia-komandy-touch 

Резюме:

**** Недостатком или достоинством (зависит от цели использования), является то ,что перечисленные в аргументах файлы выводятся на терминал вместе  (отсюда имя cat (catenate) – соединять), один за другим, без каких либо разделителей, ну и понятно если результирующий файл длинный, то удобнее передать его в канале  програме постраничного просмотра (пролистывания) или другое название "пэйджеры", почему? и при чем здесь это древнее устройство мобильной связи? ...."тайна сия велика" например: 

| more постранично 

| less построчно

| pg   использует интерфейс, аналогичный vi , но команды другие 

pr  ....и тд.


PS: Есть и "цветной cat" с подсветкой синтаксиса(настраиваемая) и другими полезными функциями называется ccat, ставится с  github:

$ wget https://github.com/jingweno/ccat/releases/download/v1.1.0/linux-amd64-1.1.0.tar.gz

$ tar xfz linux-amd64-1.1.0.tar.gz

$ sudo cp linux-amd64-1.1.0/ccat /usr/local/bin/

$ sudo chmod +x /usr/local/bin/ccat

$ ****Конечно пользоваться github это личный выбор каждого.

https://ubunlog.com/en/ccat-color-output-cat/ 

Нельзя не упамянуть про утилиту tac, это противопложность команде cat, если cat читает файл с верху в низ, то tac читает снизу в верх, вся разница.

PS: Не совсем чтобы вся....например:

$ tac > tictac

1234567

asdfghj       

qwertyu

$ tac tictac

1234567

asdfghj

qwertyu

$ cat tictac

qwertyu

asdfghj

1234567

После ввода из stdin нажать Ctrl+D, но не Ctrl+C

Ctrl + C выполняет прерывание процесса. Результат действия Ctrl + D такой же. Однако разница между этими двумя способами выхода 

есть, и разница вообщем-то принципиальная:

Нажатие Ctrl + C заставляет терминал послать сигнал SIGINT (Signal - interrupt, сигнал с номером 2) процессу, который на данный момент его контролирует. Когда foreground-программа получает сигнал SIGINT, она обязана прервать свою работу, поэтому для tac нажатие Ctrl + C приведет к отсутствию результата (надо попробовать и все станет очевидным)

Нажатие Ctrl + D говорит терминалу, что надо зарегистрировать EOF (end of file – конец файла), то есть выполнить дамп памяти для процесса, то есть поток ввода окончен, сигнал SIGQUIT (Signal - quit сигнал с номером 3).  Для Bash это значит выйти из программы. Конечно  "неискушенному юзеру" совершенно плевать чем отличается Ctrl+D, от Ctrl+C, но это важно, и обязательно придет позже, что Ctrl+D это end of file.

Комбинация клавиш Ctrl + Z посылает процессу сигнал остановиться SIGTSTP (Signal TTY Stop, сигнал с номером 20), для возобновления процесса служит сигнал SIGCONT (сигнал с номером 18) ). Это значит, что процесс остается в системе, но замораживается – в фоновый режим. С помощью команды bg его можно снова запустить, оставив при этом в фоновом режиме.  Команда fg не только возобновляет ранее приостановленный процесс, но и выводит его из фона на передний план, и опять таки посредствам определенных сигналов, всю таблицу сигналов можно увидеть набрав в терминале $ kill -l.

Строковый редактор ed

https://drive.google.com/file/ED   <<--------PDF

ED (editor) — первый стандартный текстовый редактор операционной системы UNIX, прототип будущих vi и vim, родоначальник семейства потоковых редакторов, таких как sed Stream ED который и по сегодняшний день является эфективным и востребованным средством обработки данных. ED был написан Кеном Томпсоном на языке ассемблера в 1971 году. 

Чтобы создать с помощью ed файл с именем junk, содержащий некоторый текст, выполним следующее:

$ ed                     Вызывает текстовый редактор

a                           команда ed для добавления текста теперь можно вводить текст ...

.                            Введите отдельно «.» – завершение ввода текста

w junk                 Записать текст в файл с именем junk

39                        ed выводит количество записанных символов

q                          Выйти из ed

$

Команда a (append – добавить) сообщает ed о начале ввода текста. Символ «.», обозначающий конец текста, должен быть введен в начале отдельной строки. Не забудьте его – до тех пор пока этот символ не будет введен, ни одна из последующих команд ed не будет распознана – все, что вводится, будет восприниматься как продолжение текста. Команда редактора w (write – записать) сохраняет введенную информацию;  w junk сохраняет ее в файле с именем junk. Любое слово может выступать в качестве имени файла; в данном примере было выбрано слово junk (мусор), чтобы показать, что файл "очень" важный. В ответ ed выдает количество символов, помещенных в файл. До ввода команды w ничего записано не будет, так что если отключиться и уйти, то информация не будет сохранена в файле. (Если отключиться во время редактирования, то данные, которые обрабатывались, сохраняются в файл ed.hup, с ним можно продолжать работать в следующей сессии.)

Счетчики количества символов в ed учитывают и символ конца каждой строки, называемый разделителем строк (newline), с помощью которого система представляет Return. В современных кодировочных таблицах под хранение информации о коде каждого символа отводится 1 байт (не во всех).

1 символ = 1 байт

Если во время редактирования происходит отказ системы (то есть из за сбоя аппаратного или программного обеспечения система внезапно останавливается), то файл будет содержать только те данные, которые были записаны последней командой write. После же выполнения w информация записана "навсегда"; чтобы получить к ней доступ, введите $ ed junk.

Опции:  -  Подавление вывода посторонней информации (число строк, диагностика)

Командные последовательности:

.... приемственность vi очевидна. Команды:

«Специалисты в области computer science любят ed не потому что он пришел первым, а потому что он стандартный. Все остальные любят ed потому что это ED!, это "Old school"»

VI - текстовой редактор операционной системы

www.cs.colostate.edu/helpdocs/vi.html 

Значение текстового редактора для *nix систем, то что называется "переоценить не возможно" и поскольку редактор ed был довольно сложным для «простого смертного», George Coulouris разработал редактор em (editor for mortals — редактор для смертных). Билл Джой модифицировал редактор em и назвал его en, а позже на его основе создал ex, в котором появился визуальный режим, вызывавшийся командой vi. Так как пользователи больше времени проводили в визуальном режиме, ставший частью 2BSD, редактор сразу запускался уже в нём.  Так появился vi, бывший в то время всего лишь жёсткой ссылкой на ex,  и на сегодняшний день в современных Linux мы имеем:

~$ uname -v

 Debian 5.10.46-4kali1 (2021-08-09)

~$ type em

bash: type: em: not found

~$ type en

bash: type: en: not found

~$ type ed

ed is /bin/ed

~$ type ex

ex is /usr/bin/ex

~$ type vi

vi is /usr/bin/vi

~$ type vim

vim is /usr/bin/vim

Название конфигурационного файла для vi - .exrc и до ныне, и вот каким то не хитрым способом (очевидно через ядро) они связаны и работают исключая необходимость установки дополнительных редакторов и файловых менеджеров, но современный user врят ли обойдется без двух панельных менеджеров типа: "Midnight commander", vi подобного "Ranger" и копипастового "Nano".

Личность Билла Джой (полное имя Уильям Нельсон Джой, William Nelson Joy, 8 ноября 1954 года, Детройт) — американского учёного в области теории вычислительных систем, разработчика программного обеспечения для UNIX, доктора философии, аналитика, лауреат премии имени Грейс Мюррей Хоппер автора популярного текстового редактора vi и командной оболочки csh, не вникая можно оценить просто по биографии:

Закончил Мичиганский университет, получив титул бакалавра по электротехнике, и продолжил обучение в Калифорнийском университете в Беркли, где он обрёл степень доктора философии в 1979 году. Его научным руководителем в Беркли являлся профессор Боб Фэбри, основатель исследовательской группы Computer Systems Research Group, в которой Билл Джой работал над BSD Unix. 

В 1982 году Джой стал одним из основателей компании Sun Microsystems в которой проработал более 20 лет, принимал участие в разработке микропроцессоров SPARC, языка программирования Java и технологий JINI и JXTA. 

Первая версия была написана Биллом Джоем в 1976 году, vi и по сей день входит по умолчанию наверное во все *nix системы, что вполне закономерно исходя из того что vi это "редактор операционной системы" в котором нет необходимости иметь всякого рода идиотские фичи, простота и надежность это и есть vi, естественно user всегда стремиться к избыточности, поэтому существует vim. Редактор писался для терминала ADM-3A, имевшего ограниченную клавиатуру, на ней не было выделенных клавиш-стрелок, а из модификаторов доступны только Shift и частично Ctrl. Эти обстоятельства и повлияли на выбор используемых в редакторе клавиш. 

Интерфейс "спартанский - ни чего лишнего" предельно простой:

.exrc


set exrc

set list               Показать неотображаемые символы

set nu               Пронумеровать строки

set ts=[num]    Установить значение табуляции


                                       "Using a free version of vi is not a sin but a penance"

                                                                                Richard Matthew Stallman


PS: Люди распускающие "слухи" о "недружелюбности" vi, это люди ленивые или пользователи Windows, ...... здоровая доля "мозахизма" стимулирует умственный процесс.

Команда  Описание

:q!      Выход без сохранения

:w      Сохранение изменений

:w <filename>     Сохранение как <filename>

:wq              Выход с сохранением

:q      Выход, если файл не изменялся

i      Переход в режим вставки символов в позиции курсора.

a      Переход в режим вставки  в позиции после курсора.

o      Вставка строки после текущей

O      Вставка строки над текущей

x      Удаление символа в позиции курсора

dd      Удаление текущей строки

u      Отмена последнего действия

<escape>             Возврат в режим команд  

Pipe

Канал одна из фундаментальных абстракций наряду с файлом и процессом –  способ подключения вывода одной программы на вход другой без каких бы то ни было временных файлов; а конвейер (pipeline) – это соединение двух или более программ посредством каналов, очевидный пример межпроцессорного взаимодействия – IPC.

Можно дать и такое определение: ... в процессе построения программ из конструкционных элементов меньшего размера  часто используются каналы как и перенаправление ввода-вывода при сборке и соединении отдельных частей. В результате, одни программы(модули) могут работать вместе с другими, использование каналов имеет еще один большой плюс, канал делает не нужным создание временных файлов, а работает через буфер ядра операционной системы иными словами через "разделяемую память". 

Или такое: ....каналом (pipe) называется способ "переадресации" данных, при котором результаты работы одной команды передаются другой команде в виде входных данных, с помощью каналов программы могут быть объединены в конвейеры и в конвейер может быть включено любое количество программ.

Какое ни давай, канал как способ взаимодействия различных процессов, ключевая "веха" в развитии Unix.

алгоритм pipe

входная информация: отсутствует

выходная информация: дескриптор файла для чтения дескриптор файла для записи

{

назначить новый индекс из устройства канала (алгоритм ialloc); 

выделить одну запись в таблице файлов для чтения, одну — для переписи; 

инициализировать записи в таблице файлов таким образом, чтобы они указывали на новый индекс;

выделить один пользовательский дескриптор файла для чтения, один — для записи, проинициализировать их таким образом, чтобы они указывали на соответствующие точки входа в таблице файлов;

установить значение счетчика ссылок в индексе равным 2; 

установить значение счетчика числа процессов, производящих чтение, и процессов, производящих запись, равным 1;

 

Канал организуется с помощью оператора "|" синтаксис таков:  команда1 | команда2

$ ls | grep f_desc | xargs cat

#!/bin/sh

$f_desc

exec 3<&0 0<myfile

read line1

read line2

exec 0<&3

echo $line1

echo $line2

В приведенном примере команда ls формирует список всех файлов из текущего каталога. Этот список был бы выведен на экран, если бы не символ канала. Интерпретатор shell обнаруживает канал, перехватывает все выходные потоки команды, стоящей слева от оператора |, и направляет их команде, которая расположена справа от оператора. В данном случае утилите фильтрации grep, которая отбирает в списке файл с именем "f_desk", и передает команде cat выводящей на терминал содержимое файла,...НО! ни чего подобного бы не произошло нибудь "чудесной" команды xargs "каноническом" способе передачи данных из stdin другой команде в качестве аргументов, то есть без xargs команда cat не получила бы в качестве аргумента результат поиска команды grep (имя файла),...  но это все часности, а смысл примера в том, что именно так, или почти так создаются конвееры из отдельных команд, по средствам каналов. 

При обработке строковых данных можно объединять, каналами такие  программы фильтрации, как потоковый редактор sed, редактор awk , утилиту grep, и прочее, создавая сложные критерии отбора информации, по средствам объединения процессов (программ) эту информацию обрабатывающих.

 $ sudo df

Файл.система 1K-blocks      Использовано    Доступно    Использовано%    Cмонтировано в

/dev/sda1         14882736     10988016            3115664       78%                          /

none                  4                    0                           4                     0%                   /sys/fs/cgroup

udev                  827624         4                          827620          1%                      /dev

tmpfs                168640         1080                     167560          1%                      /run

none                 5120              0                          5120              0%                      /run/lock

none                 843200         88                         843112          1%                      /run/shm

none                 102400         12                         102388          1%                      /run/user

Share                525903808  474652336            51251472    91%                     /media/sf_Share


$ sudo df|awk '{print $1}'|grep -v "Файл.система"

/dev/sda1

none

udev

tmpfs

none

none

none

Share

В приведенном примере командная строка ($ sudo df | awk '{print $1}' | grep -v "Файл.система") служит для вывода списка всех смонтированных файловых систем. Команда df формирует расширенный список с указанием всевозможных статистических данных об использовании каждой файловой системы. Программа awk извлекает из этого списка только первый столбец с именами файловых систем, а команда grep -v удаляет заголовок этого столбца, оставляя только имена, для наглядности команда df (в первой части примера) выполнена отдельно, и в отличии от примера приведенного выше, где при помощи xargs был передан аргумент, в этом примере происходит обработка "потока, строковых данных", опять таки при помощи конвеера команд. 

В следующем примере команда sort сортирует строки текстового файла myfile, а результат посылается на принтер:   $ sort myfile | lp

FIFO

Очень желательно понимать, что кроме безымянного(не поименованного, он же "програмный") канала создаваемого системной функцией pipi() синтаксически обозначаемого вертикальной чертой | , Существуют "именованные" каналы создаваемые системной функцией mkfifo() mknod() или просто FIFO first in first out. Вся радость именованного канала ,что он использует специальный файл который мы можем создать в любом месте файловой системы с необходимыми нам правами доступа, с помощью команды mkfifo проще говоря make fifo, например;

$ mkfifo pipe

$ ls -l pipe

prw-r--r-- 1 user user 0 Jul 16 15:44 pipe|

И видим файл именованного (потому что у него есть имя и звать его pipi. в нашем случае) канала открытый для чтения всем, для записи только владельцу

Есть некоторые особенности в использовании именованных каналов, поскольку это FIFO данные в канале содержатся до тех пор пока их кто нибудь не считал и когда все  читающие и  пишущие процессы завершаются, все непрочитанные данные исчезают  и блоки  памяти, используемые каналом, освобождаются. Однако, запись  в директории,  показывающая права  доступа  к  каналу, сохраняется до тех пор, пока не будет удалена

Например:

$ echo "Именованный канал" > pipe

открываем другой терминал, поскольку нам нельзя завершать процесс:

$ cat pipe

Именованный канал

$ возврвщаясь к первому терминалу видим, что после чтения из канала процес завершился самостоятельно, в чем можно убедиться повторив чтение из канала;

$ cat pipe

...канал откроется но в нем ни чего нет.

Все эти фокусы можно проделать и с одного терминала, воспользовавшись переводом процесса в фон.:

$ echo "Именованный канал" > pipe &

[1] 220910

$ cat pipe

Именованный канал

[1]+  Done                    echo "Именованный канал" > pipe

Надо вспомнить что процессы, взаимодействующие через неименованный (програмный) канал,  должны быть  родственными. В то время как именованные каналы,  в отличие  от неименованных, могут использоваться неродственными процессами в том числе и удаленными.  Они дают  нам, по сути, те же возможности, что и  неименованные каналы, но с некоторыми преимуществами, присущими обычным файлам и если в оболочках сплошь и рядом используется pipe (не именованный канал), то операционная система сплош и рядом использует fifo(именованные), для оболочек именованный канал удобное средство перемещения данных между командами. Существует масса хитромудрых комбинаций использования именованных каналов. 

И еще раз можно повторить для себя, что "традиционный" (неименованный, програмный) канал "безымянен" поскольку существует анонимно и только на время исполнения процесса, через буфер ядра, именованный канал — существует в системе и после завершения процесса, он должен быть «отсоединён» или удалён когда уже не используется, от сюда надо думать и появилась идея "сокетов".

Можно дополнить, что именованные каналы — это также сетевой протокол в SMB, любимый протокол Microsoft. И хотя это прозвучит голословно, но и ролевая модель RBAC глубоко уважаемой компании "Sun Microsystems" в полной мере использует именованные каналы, иначе как бы они достигали столь чудесных результатов.

tee

Великолепная утилита, очень похожа на cat и во многих ситуациях удобнее использовать именно tee.

Команда tee - "тройник" работает следующим образом: входные данные копируются, при этом одна копия направляется в стандартный поток вывода, а другие копии — в указанные файлы.  Эта утилита соответствует своему имени (tee — тройник): она берет единый поток входной информации и отправляет его по двум направлениям. 

tee [ПАРАМЕТР]... [ФАЙЛ]...

-a --append                      добавлять данные к указанным ФАЙЛам, не перезаписывать

-i --ignore-interrupts      игнорировать сигналы прерываний

Опция задает добавление выводимых данных в конец файла (по умолчанию производится замена содержимого файла).

Команду tee удобно применять в том случае, когда необходимо вести журнал выводимых данных или сообщений.

 

Рассмотрим пример. Команда who формирует список пользователей, которые зарегистрированы в данный момент в системе, а команда tee отображает этот список на экране, направляя копию в файл who.out.

$ who | tee who.out

imint tty8 2015-07-26 16:09 (:0)

imint pts/3 2015-07-26 16:49 (:0.0)

$ cat who.out

imint tty8 2015-07-26 16:09 (:0)

imint pts/3 2015-07-26 16:49 (:0.0)

Можно направлять вывод нескольких команд в один и тот же файл, не забывая применять опцию .

$ sort myfile | tee -a accounts.log 

$ myscript | tea -a accounts.log

tail

Созвучная с tee и не менее востребованная команда tail позволяет вывести заданное количество строк файла "с низу", аналогичная команда head "с верху" например:

$ who -a | tee who.out 

           system boot  2023-10-11 11:09

LOGIN      tty1         2023-10-11 11:10               879 id=tty1

           run-level 5  2023-10-11 11:10

Пусть файл будет очень длинным, например системный журнал и нам интересны только последние события

$ tail -1 who.out

           run-level 5  2023-10-11 11:10

$ tail -2 who.out

LOGIN      tty1         2023-10-11 11:10               879 id=tty1

           run-level 5  2023-10-11 11:10

Зачастую отдельно не используется, а используется в сочетании с AWK, SORT, GREP..и прочее, как и командой fold, позволяющей "форматировать" вывод под экран монотора, но наиболее часто используется когда надо дописать что либо  в файл и посмотреть дописанное:

$ echo "дополнение -1" >> who.out | tail -1 who.out

дополнение -1

Более эстетичный способ все та же команда tee, за счет опции -a (добаить в указанный файл не перезаписывая, без опции перезапишет):

$ echo "дополнение -2" | tee -a who.out

дополнение -2

$ cat who.out 

           system boot  2023-10-11 11:09

LOGIN      tty1         2023-10-11 11:10               879 id=tty1

           run-level 5  2023-10-11 11:10

дополнение -1

дополнение -2

$ echo "дополнение -3" | tee who.out 

дополнение -3

$ cat who.out 

дополнение -3

и конечно самый простой способ дописать (без выкрутасов) это использовать перенаправление:

$ echo "дополнение -" >> who.out

$ cat who.out 

дополнение -3

дополнение -4

Обработка результатов сортировки с помощью команд head и tail


pee  moreutils package


Не менее интересная команда pee из пакета moreutils, тоже "тройник", тройник позволяющий выводить srdout в различные каналы, например;

$ echo "Show this forward and in reverse" | pee cat rev 

Show this forward and in reverse

esrever ni dna drawrof siht wohS

или

$ echo "Linux is Fun!" | pee cat 'cut -d" " -f1' 

Linux is Fun!

Linux

Или транслировать команду на несколько узлов:

$ echo "uptime" | pee "ssh host1" "ssh host2" "ssh host3" 

Более наглядно:

$ echo "uptime" | pee "cat > file1" "cat > file2" "cat > file3"; ls -l file*

-rw-r--r-- 1 user 7 Jun 13 11:57 file1

-rw-r--r-- 1 user 7 Jun 13 11:57 file2

-rw-r--r-- 1 user 7 Jun 13 11:57 file3

$ cat file1 file2 file3 

uptime

uptime

uptime

Не менее забавная утилита xargs

exec

https://sites.google.com/site/bashhackers/commands/exec

http://espressocode.top/exec-command-examples/

http://rus-linux.net/consol/exec-in-command-find

https://unix.stackexchange.com/how-to-run-find-exec

Системный вызов exec, одна из ключевых функции операционной системы, способ "наполнить" вновь созданный процесс содержанием или заменить прежнее fork-and-exec.   

Команда exec заменяет текущий интерпретатор shell указанной командой. Обычно она используется для того, чтобы закрыть текущий интерпретатор и запустит другой, как и в качестве стандартной процедуры запуска новой программы называемой fork-and-exec (здесь). Но у нее есть и другое применение. Например, команда вида ехес < файл делает указанный файл стандартным входным потоком всех команд, выполнить ее в интерактивном режиме нет смысла — она предназначена для использования в сценариях, чтобы все идущие после нее команды читали свои входные данные из файла. В этом случае в конце сценария обязательно должна стоять команда ехес <&- которая закрывает входной поток (в данном случае файл). Подобный прием применяется преимущественно в сценариях, выполняющихся при выходе из системы.

Итого встроенная команда exec применяется чтобы:

$ exec > ttt

$ echo "Это \"та самая\" команда exec,"

$ echo "она заменила стандартный вывод stdout, на вывод в файл \"ttt"\"

$ exit

$ cat ttt

Это "та самая" команда exec,

она заменила стандартный вывод stdout, на вывод в файл "ttt"

Еще проще:

$ cat > exxec

#!/bin/bash

echo 123456

exec > ttt1

cat ttt1

^C

$ . exxec

123456


Пример сцеария где команда  exec < data-file перенаправляет ввод с stdin в файл в результате весь ввод, вместо stdin, будет производиться из этого файла, что дает возможность читать содержимое файла, строку за строкой, анализировать каждую введенную строку, например с помощью sed и awk и т.д.  (https://poplinux.ru/adv-bash )

$ cat data-file

sdfg

xcvb

xcvb

$ cat > eeexxx

#!/bin/bash

# Перенаправление stdin с помощью 'exec'.

exec 6<&0          # Связать дескриптор fd6 со стандартным вводом stdin.

exec < data-file   # stdin заменяется файлом "data-file"

read a1            # Читается первая строка из "data-file".

read a2            # Читается вторая строка из "data-file."

echo

echo "Следующие строки были прочитаны из файла."

echo "===================="

echo $a1

echo $a2

echo "===================="

exec 0<&6 6<&-

# Восстанавливается stdin из fd6(0<&6), где он был сохранен как результат выполнения exec 6<&0

# далее fd6 закрывается(6<&-) освобождая его для других процессов(<&6 6<&- даст тот же результат).

echo -n "Введите строку:  "

read b1  # Теперь функция "read" может принимает данные с обычного stdin.

echo

echo "Строка, принятая из stdin:" $b1

echo


$ . eeexxx

Следующие строки были прочитаны из файла.

====================

sdfg

xcvb

====================

Введите строку:  tetetetet


Строка, принятая из stdin: tetetetet



Команда exec, на первый взгляд кажется очень "загадочной", однако обратившись к фундаментальным идеям устройства, построения "Unix", мы выясним что все ее "шаманства" кроются именно там, и ни какой "черной магии"!, воспользуемся например прекрасной книгой Мориса Баха "Архитектура операционной системы UNIX", и поскольку здесь нет места раскрывать "тему", тем более, что автор делает это достаточнр полно (7.5 Вызов других програм)  , приведем лишь пример алгоритма выполнения системной функции exec:

алгоритм ехес 

входная информация:

выходная информация: отсутствует

{

получить индекс файла (алгоритм namei);

проверить, является ли файл исполнимым и имеет ли пользователь право на его исполнение;

прочитать информацию из заголовков файла и проверить, является ли он загрузочным модулем;

скопировать параметры, переданные функции, из старого адресного пространства в системное пространство;

for (каждой области, присоединенной к процессу) отсоединить все старые области (алгоритм detachreg);

for (каждой области, определенной в загрузочном модуле) { выделить новые области (алгоритм allocreg); 

присоединить области (алгоритм attachreg);

загрузить область в память по готовности (алгоритм loadreg);

}

скопировать параметры, переданные функции, в новую область стека задачи;

специальная обработка для setuid-программ, трассировка;

проинициализировать область сохранения регистров задачи (в рамках подготовки к возвращению в режим задачи);

освободить индекс файла (алгоритм iput);

}

И тем не менее все равно встает вопрос, зачем подобный инструмент по замене процесса оболочки выполняя его не как "новый процесс", предоставлять в руки "дикому, потенциально склонному к разрушению" user-у, и это конечно наводит на совершенно закономерные конспирологические размышления ........

exec, применение дескрипторов файлов

Возвращаясь к дескрипторам файлов еще раз, команда ехес < файл не только назначает файл стандартным входным потоком всех команд сценария, но и при необходимости перезаписывает указатель на файл с дескриптором fd0 (stdin), или любой другой, восстановить дублированный указатель можно будет только по завершении работы сценария. Если же в сценарии предполагается продолжить чтение данных с клавиатуры, то необходимо каким-то образом сохранить указатель назначив ему другой дескриптор в нашем случае это будет fd3: exec 3<&0

Здесь приведен небольшой сценарий, в котором демонстрируется, как это сделать и демонстрирующий гибкость которую дает применение exec.

Первая команда exec сохраняет указатель на стандартный входной поток (stdin) в файле с дескриптором 3 (допускается любое целое число в диапазоне от 3 до 9), а затем открывает файл myfile для чтения. Следующие две команды read читают из файла две строки текста. Вторая команда ехес восстанавливает указатель на стандартный входной поток: теперь он связан с stdin, а не myfile, запись 3<&- закрывает дескриптор 3. Завершающие команды echo отображают на экране содержимое прочитанных строк, которые были сохранены в переменных line1 и line2 и печатает ввод с терминала.

PS: bash man page: Оператор перенаправления [n]<&word используется для дублирования дескрипторов входных файлов. Если слово расширяется до одной или нескольких цифр, файловый дескриптор, обозначенный n, делается копией этого файлового дескриптора. Если цифры в слове не указывают дескриптора файла, открытого для ввода, возникает ошибка перенаправления. Если слово оценивается как «-», файловый дескриптор n закрывается. Если n не указано, используется стандартный ввод (файловый дескриптор 0), то есть в нашем примере запись 3<&- похоже избыточна, но корректна. "Относительно" наглядно это можно продемонстрировать так:

$ echo $$ # узнаем PID

118212

$ ls -lah /proc/118212/fd/

total 0

dr-x------ 2   0 Jul 26 15:57 ./

dr-xr-xr-x 9   0 Jul 26 15:56 ../

lrwx------ 1  64 Jul 26 15:57 0 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 1 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 2 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 255 -> /dev/pts/1

на файл с дескриптором 255 можно не обращать внимания, он открыт для каких то нужд bash

$ exec 3<&0 # перенаправим(свяжем) stdin и дескриптор fd3

$ ls -lah /proc/118212/fd/

total 0

dr-x------ 2   0 Jul 26 15:57 ./

dr-xr-xr-x 9   0 Jul 26 15:56 ../

lrwx------ 1  64 Jul 26 15:57 0 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 1 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 2 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 255 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:58 3 -> /dev/pts/1

$ exec 3<&- # закроем fd3

$ ls -lah /proc/118212/fd/

total 0

dr-x------ 2   0 Jul 26 15:57 ./

dr-xr-xr-x 9   0 Jul 26 15:56 ../

lrwx------ 1  64 Jul 26 15:57 0 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 1 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 2 -> /dev/pts/1

lrwx------ 1  64 Jul 26 15:57 255 -> /dev/pts/1

Можно заметить что дескриптор 0 -> /dev/pts/1 не закрывается, а происходит его дублирование, связывание c fd3 и команда exec необходима эдесь для того чтобы далее производить над ним какие либо действия. То есть мы сначала скопировали stdin в fd3, и создали его как процесс (или наоборот, в любом случае системный вызов exec делает то что и должен делать "по определению"), далее закрываем fd3, чем возвращаем stdin штатный дескриптор.


$ cat f_desc

#!/bin/sh

$f_desc

exec 3<&0 0<myfile

read line1

read line2

exec 0<&3 3<&-

echo $line1

echo $line2

echo -n "Напечатайте:  "

read stdin

echo "Это stdin:" $stdin 

$

Файл myfile содержит следующий текст:

$ cat myfile

line -1

line -2

line -3

EOF

И результат работы сценария:

$ sh f_desc

line -1

line -2

Напечатайте:  fffffffffff

Это stdin: fffffffffff

Команда chmod +x f_desc сделает файл исполняемым, для выполнения скрипта существует source (.), волшебная запись - точка, слеш (./), или просто имя интерпретатора с аргументом "имя исполняемого файла". 

Еще одна чудесная способность exec логично ему присущая:  

"Процесс может сменить свой UID, если запустит вместо себя при помощи exec() другую программу из файла, имеющего атрибут SetUID, тогда UID процесса станет равным UID файла.", как слабое утешение есть "POSIX Capabilitie", но самое лучшее решение давно придумал SUN, называется "Role-based access control", где пользователя "root" нет по определению 

$ capsh --print

..............................

Securebits: 00/0x0/1'b0

 secure-noroot: no (unlocked)

 secure-no-suid-fixup: no (unlocked)

 secure-keep-caps: no (unlocked)

 secure-no-ambient-raise: no (unlocked)

Постоянное перенаправление

Еще один полезный способ применения exec и перенаправления, для скриптов, позволяющий сократить объем написания кода:

$ cat > exxec

exec 1>outfile

echo "This is a test of redirecting all output"

echo "from a shell script to another file."

echo "without having to redirect every line"

^C

$ sh exxec

$ cat outfile

This is a test of redirecting all output

from a shell script to another file.

without having to redirect every line

$ https://habr.com/ru/company/blog <------- хорошая статья

Порядок выполнения команд

При выполнении команды иногда требуется знать, как была выполнена другая команда? Предположим, необходимо скопировать все файлы из одного каталога в другой, а затем удалить исходный каталог. Прежде чем удалять исходный каталог, важно убедиться, что копирование прошло успешно. В противном случае содержимое исходного каталога может оказаться утерянным, вопрос в том как выяснить насколько успешно или нет была выполнена предудущая команда и для этого предназначен механизм под названием "код возврата", статус выполнения команды, реализованный в качестве переменной, (код возврата $?), это одна из часто востребованных переменных оболочки, способ не потеряться в ошибках. 

Пояснить это можно вспомнив, что после своего выполнения любая команды возвращает числовой код, результата выполнения команды: 

Ø TRUE

1 FALSE  

Если это Ø -TRUE - значит команда выполнена успешно, если это число отличное от нуля - значит команда завершилась с ошибкой и соответственно можно строить выполнение последовательности других команд учитывая этот факт. Выражаясь  грамотно, true и false в логике называются предикатами , способ соотнести колличественные, числовые значения которыми оперирует вычислительная техника с логическими которыми оперирует человек.

При создании сложных инструкций большую роль играют операторы && и || (двойной амперсанд - && и двойной “пайп” - ||), которые группируют команды по принципу логического И/ИЛИ, другое название логические операторы, операторы сравнения, булевы (boolean) операторы, обладают двумя значениями (true, false) — традиционные булевы значения. Они позволяют выполнить указанную после них команду или группу команд только в том случае, если была (или не была) успешно выполнена предыдущая команда или группа команд.

Если объединение команд происходиют только через &&, то каждая следующая команда будет выполняться, только в случае TRUE, успешного завершения предыдущей команды. Если объединение команд происходит только через ||, то каждая следующая команда будет выполняться, только в случае FALSE, неудачного завершения предыдущей команды Как только какая либо команда цепочки вернет код возврата отличный от нуля, в случае && следующие после нее команды не будут выполнены и наоборот в случае ||. 


Стандартный пример для Linux: $ sudo apt update && apt upgrade, (на первый взгляд "красивая конструкция", но по скольку первая часть команды скорее всего будет выполнена с ошибками, то вторую придется вводить снова, потому ей никто и не пользуется) операторы && и ||, часто применяются в управляющих конструкциях для изменения хода выполнения сценария при проверке условий, if [FALS] || [TRUE]; then. Пример: 

if [ "$ANS" = "у" ] || [ "$ANS" = "Y" ]; then

Пользователь ввел "y"

первое условие TRUE

второе сравнение не выполняется, в итоге if/then = TRUE

Пользователь ввел "Y"

первое условие FALSE

выполняется второе условие

второе условие TRUE, в итоге if/then = TRUE, если один из операндов имеет значение TRUE.

Если пользователь введет что либо отличное от "y" или "Y"

в итоге будет if/then = FALSE , и соответственно ход сценария изменится в нужном направлении. Вообщем && и || — это один из способов создавать сложные условия, управляющие конструкции (test):

if [ a = b ] && [ c = d ] равно if test a = b && test c = d , но не так if [[ a = b ] && [ c = d ]]


Существуют также операторы () - простые скобки и {} - фигурные скобки, объединяющие заключенные в них команды в группу, выполняемую в текущем и порожденном интерпретаторе shell, что является одним из важных свойств в различии скобок.

() - Команды размещенные в скобках, выполняются в дочернем процессе ( subshell ). При этом переменные, определяемые в дочернем процессе, не видны в родительском. 

{} - Блок кода ( вложенный блок). По сути такая конструкция создает анонимную функцию. В отличии от традиционно создаваемых функций, переменные вложенного блока, доступны всему сценарию, в отличии от конструкций с обычными одинарными скобками, выполняющимися в дочернем процессе, вложенные блоки в фигурных скобках, выполняются в рамках того-же процесса, что и сам сценарий.


Оператор &, утилита nohup


Символ & означает, что вы собираетесь выполнить определенную команду в фоне или в качестве задания, то есть создать фоновый процесс, можно запускать процессов сколько захотите, исходя из количества ресурса (обычно оперативной памяти)

Синтаксис такой: $ command &

Закрывая терминал мы закрываем и дочерние процессы, чтобы этого не произошло можно просто закрыть потоки (stdout stdderr) и остаться в прежней сессии: 

$ command > /dev/null 2>&1 &

В результате  command > /dev/null stdout в /dev/null а 2>&1 & ошибки в stdout

Запись конечно "не человеческая", но если читать справа на лево, можно понять смысл и даже привыкнуть

Узнать состояние всех остановленных и выполняемых в фоновом режиме задач в рамках текущей сессии терминала можно 

при помощи утилиты jobs c ключом -l: $ jobs -l

В любое время можно вернуть процесс из фонового режима на передний план. Для этого служит команда fg: $ fg

Если в фоновом режиме выполняется несколько программ, следует также указывать номер задания: $ fg %1

Завершит фоновый процесс: $ kill %[номер задания], просто kill PID


$ echo $ &

[2] 168426

$

[1]   Done         echo

https://intellect.icu/protsessy-zadachi-komandy

Чтобы не связывать себя текущей сессией терминала, есть утилита nohup "HUP (hang-up oтбой)" например:

$ nohup ping 8.8.8.8 &

[1] 56994

$ nohup: ignoring input and appending output to 'nohup.out'  #сообщение о том,что nohup игнорирует ввод (https://coderoad-nohup).

$ ^C 

Откроем другую сессию терминала и выполним $ ps aux |  grep [5]6994     (grep [5]6994  -  убрать из вывода grep "grep")

$ ps aux | grep [5]6994

user       56994  0.0  0.0   7192   912 ?        S    15:44   0:00 ping 8.8.8.8

Закроем ВСЕ терминалы, и во вновь запущенном выполним:

$ ps aux | grep [5]6994

user       56994  0.0  0.0   7192   912 ?        S    15:44   0:00 ping 8.8.8.8

$

И выход только один:

$ kill 56994

$ ps aux | grep [5]6994


В итоге, чем же занимается эта чудная утилита?, как оставить процесс выполняющимся завершив сессию терминала?, ответ очевидный, в применении все того же перенаправления ввода-вывода конкретно stdout, связанного с дескриптором 1, ....вообщем,  nohup создает файл, по умолчанию это 'nohup.out' и отправляет туда stdout(1), в чем можно убедиться выполнив:

$ ls -l nohup.out

-rw------- 1 user user 163K Dec 31 16:18 nohup.out

или:

$ cat nohup.out

.........................................................

64 bytes from 8.8.8.8: icmp_seq=2071 ttl=107 time=18.3 ms

64 bytes from 8.8.8.8: icmp_seq=2072 ttl=107 time=17.7 ms

$


И увидеть результаты работы "ping" в фоне, умолчания естественно можно изменить, создав еще одно перенаправление, перенаправление в свой файл, заодно направив туда и ошибки, например:

$ nohup ping 8.8.8.8 > pinghup 2>&1 &

[1] 31952

$ ps aux | grep [3]1952

user       31952  0.0  0.0   7192   912 pts/0    S    19:21   0:00 ping 8.8.8.8

$ kill 31952

$ ps aux | grep [3]1952

[1]+  Terminated              nohup ping 8.8.8.8 > pinghup 2>&1

$

Проверить файл"pinghup":

$ cat pinghup

nohup: ignoring input

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

64 bytes from 8.8.8.8: icmp_seq=1 ttl=107 time=17.1 ms

......................................................

$


$ nohup ping 8.8.8.8 > pinghup 2>&1 &      #Опять таки справа на лево: 2>&1 ошибки в stdout, stduot команды в файл "pinghup". 

PS: если надо запустить несколько заданий, можно создать файл сценария, эти задания включающий, и запустить на исполнение с использованием nohup.


Резюмируя можно сказать, что выпонение процессов в фоне важная и полезная функция, наверно особенно в плане мониторинга, стандартный пример утилита tail и файл системного журнала /var/log/syslog:

# tail /var/log/syslog &

[1] 44898

# Dec 31 19:36:08 KaliLinux org.gnome.Shell.desktop[2062]: Window manager warning: Overwriting existing binding of keysym ff55 with keysym ff55 (keycode 70).

Dec 31 19:36:08 KaliLinux org.gnome.Shell.desktop[2062]: Window manager warning: Overwriting existing binding of keysym ff56 with keysym ff56 (keycode 75).

...............................................................................

PS: Для полноты можно добавить, что команда tail включает в свой функционал ключь -f, то есть может выполняться в фоне и в итоге выражения:

# tail /var/log/syslog &  и  # tail -f /var/log/syslog  будут равнозначны.



В итоге: двойной пайп и двойной амперсанд  && и ||, группировка команд, подстановка.

Оператор &&

Логическое "И", общий формат оператора && таков:  команда1  &&  команда2

Эта инструкция обрабатывается следующим образом: правый операнд (аргумент операции; данные, которые обрабатываются командой) интерпретируется только тогда, когда левый операнд равен TRUE. 

Иными словами, вторая команда выполняется в том случае, если первая завершилась успешно. Зеркально оператору ||, когда правый операнд интерпретируется только тогда, когда левый операнд равен FALSE.   Пример, "проверка выполнения команды":

$ cp myfile myfile1 && echo OK

OK

Сообщение, заданное в команде echo, появилось на экране, значит, команда ср успешно выполнила копирование файла.

Оператор ||

Общий формат оператора || таков:  команда 1 || команда2

Эта инструкция обрабатывается следующим образом: правый операнд интерпретируется только тогда, когда левый операнд равен FALSE. Иными словами, вторая команда выполняется в том случае, если первая завершилась не успешно. Простой пример, иллюстрирующий применение оператора ||:

$ cp myfile2 myfile3 || echo FALSE

cp: не удалось выполнить stat для «myfile2»: Нет такого файла или каталога

FALSE

$ Операция копирования завершилась неудачно (исходного файла не существует), поэтому была выполнена команда echo. 

Подстановка команд, переменных, арифмитических выражений

Костромин "Linux для пользователя" 

Подстановка команд

Подстановка команд заключается в замене имени команды на результат ее выполнения. Существует две формы подстановки команд:

$(command) предпочтительней по причине "универсальности"

`command`

Если применяется вторая из этих форм, то обратный слэш внутри кавычек трактуется как литерал, кроме тех случаев, когда за ним следует $, `, или . Если же используется форма $(command), все символы внутри скобок составляют команду и ни один из них не считается специальным символом. Если подстановка производится внутри двойных кавычек, то в результатах подстановки не осуществляется разделение слов и раскрытие шаблонов имен файлов и каталогов.


Подстановка параметров и переменных

Символ $ используется для обозначения операций подстановки параметров, подстановки команд и подстановок  арифметических выражений. Выражение или имя, следующее за $, может быть заключено в скобки; что не обязательно, но удобно, так как позволяет отделить заменяемое выражение от следующих за ним слов или символов.  Таким образом, чтобы в командной строке вызвать значение параметра (в частности, любой переменной), нужно  вставить выражение вида ${parameter}. Скобки необходимы только в том случае, если имя параметра состоит из нескольких цифр, или когда за именем следует символ, который не должен интерпретироваться как часть имени.

Все значения переменных подвергаются подстановке знака тильды, раскрытию параметров и переменных, подстановке команд, подстановкам арифметических выражений, а также удалению специальных символов цитирования Разделение слов не производится, за исключением случая "$@".  Раскрытие шаблонов имен файлов и каталогов не производится.

$ — подстановка переменной

${} — то же подстановка переменной и в некоторых случаях работает только она, фигурные скобки {brace`s}, основное назначение фигурных скобок в создании "локальной области действий" именно по этому языки С, С+, С++ и многие другие, называются языками фигурных скобок, для перечисления. повторения, исключения, создание групп операторов ..., хороший пример функция или блок кода, заключающийся то же в фигурные скобки.

command $(результаты awk sed и тд) подстановка параметров, переменных в команду

command ${результаты awk,sed и тд} то же подстановка параметров, переменных в команду, с возможностью их редактировать,"expansions" расширение.

$ cat > xxx 

1234

^C

$ echo $(cat xxx)

1234

$ zzz=4321

$ echo $zzz

4321

$ echo ${zzz}

4321

$ echo ${zzz%21}

43         https://www.opennet.ru/bash_scripting_guide%     https://tldp.org/LDP/abs/BRACE 

$ echo Example: {$(cat xxx),$zzz}

Example: 1234 4321

{ls,-l} равно ls -l 

{ls,-l} это "расширение скобки" - expansions, чтобы стать ls -l

Группирование команд с помощью скобок

Существует возможность объединить несколько команд в группу и выполнить ее как единое целое в текущем или порожденном интерпретаторе shell. Во втором случае создается копия текущего интерпретатора, а все изменения среды интерпретатора отменяются по завершении последней команды в группе. Для выполнения группы команд в текущем интерпретаторе следует заключить их список в фигурные скобки, разделив команды точкой с запятой: {команда 1; команда2;...},  в дочернем (команда 1; команда2;...), соответственно

Просто выполнить группу команд, так же следует разделить их ";" 

$ ~ date +%A;date +%B;date +%C;cal

Среда

Ноябрь

20

     Ноябрь 2017

Пн Вт Ср Чт Пт Сб Вс

1  2  3  4  5  6  7 

8  9  10 11 12 13 14  

15 16 17 18 19 20 21 

22 23 24 25 26 27 28 

29 30

$ ~

{xxx,yyy,zzz,...} -- Фигурные скобки


{...} 𑂾 Блок кода или "вложенный блок"

Выполняет команды в текущей оболочке, по сути такая конструкция создает анонимную функцию. В отличии от традиционно создаваемых функций, переменные вложенного блока, доступны всему сценарию.

{...} 𑂾 Интерпретируется как список возможных вариантов. Например, следующая команда сценария, производит поиск строки test в файлах data.1, data.2, data.3:  

$ grep test data.{1,2,3*}


$ echo data{1,2,3}

data1 data2 data3


Использовать в фигурных скобках пробелы можно, либо заключив их в одинарные или двойные кавычки, либо экранировав их с помощью символа \.

$ ~ echo {test1,test2}\ :{\ A," B",' C'}

test1 : A test1 : B test1 : C test2 : A test2 : B test2 : C

$ ~

(команда1; команда2;...) -- круглые скобки: 

Чтобы выполнить группу команд в порожденном интерпретаторе shell, следует использовать круглые скобки: (команда1; команда2;...)

Команды размещенные в скобках, выполняются в дочернем процессе (subshell). При этом переменные, определяемые в дочернем процессе, не видны в родительском.

Сам по себе подобный метод применяется не часто. Обычно группа команд выполняется в составе более крупных конструкций с операторами && или ||. Результатом работы группы команд считается результат выполнения последней команды в группе.

Предположим, я выполняю сценарий comet, обрабатывающий файл month_end.txt, и в случае неудачного завершения сценария хочу прекратить работу интерпретатора shell. Простейший способ сделать это состоит в следующем:

$ comet month end.txt || exit

Но можно так же перед выходом из интерпретатора послать отвечающму за этот сценарий пользователю электронное сообщение:

$ comet month_and.txt || (echo "Привет! Твой сценарий не работает. ” | \mail dave; exit)

Символ \ в конце первой строки означает, что команда будет продолжена в следующей строке.

Арифмитические выражения в Bash

Bash предоставляет не мало способов выполнения арифметических операций, наиболее распространеные; let   expr   (( ))   bc

let

$ type let

let is a shell builtin

Если поставить кавычки - можно пользоваться пробелом, без кавычек без пробелов.

let <арифметическая операция>

$ let a=7+27

$ echo $a

34

$ let a++ #увеличить значение на 1, "а = а + 1"

$ echo $a

35

$ cat > lett

let "b = $1 + 20" #$1- позиционный параметр cli

echo $b

C^

$ . lett 10

30

$

Основные операторы:

+, -, \*, /    #умножение в let надо экранировать

var++

var--

 %  Модуль: возвращает остаток от деления


expr

$ type expr

expr is hashed (/usr/bin/expr)

более нагляден, поскольку вместо сохранения результата в переменную печатает ответ

$ expr 2 + 3

5

$ expr "2 + 3"

2 + 3   #поскольку заключено в кавычки

$ expr 2+3

2+3     #поскольку не поставлены пробелы

$ expr 13 % 3

1       #вернул остаток, деление по модулю

$ expr 12 % 6

0       #вернул остаток, деление по модулю

$ expr 12 / 6

2       #разделил

$ a=$( expr 10 - 3 )

$ echo $a

7       #результат в переменную

Двойные скобки

То что результат выполнения команды возможно сохранить в переменную, можно использовать и в арифметике используя двойные круглые скобки

$ a=$(( 4 + 3 ))

$ echo $a

7

$ a=$(( $a + 1 ))

$ echo $a

8

$ a=$((4+4))

$ echo $a

8   #без пробелов тоже можно

$ b=$(( a + 3 ))

$ echo $b

11  # без использования $ перед переменной

$ b=$(( $a + 4 ))

$ echo $b

12  #с использованием $

$ (( b++ ))       = ((b ++))

$ echo $b

13  #увеличить переменную на 1

$ (( b += 3 ))    = ((b+= 3))

$ echo $b

16  #увеличить переменную на 3

$ b=$(( 4 * 5 ))

$ echo $b

20  #символ астериска можно не экранировать

bc 

вычисления чисел с плавающей(floating) запятой

$ type bc

bc is /usr/bin/bc

$ bc

bc 1.07.1

............ 

1.3 + 1.4

2.7

1.3 * 1.4

1.8

1.3*1.4

1.8 #можно и без пробелов, но потерян разряд, что бы этого не #было делаем так:

1.30 * 1.40

1.82

1.300 * 1.400

1.820

quit

Используя переменные:

$ a=1.3

$ b=1.4

$ d=$(bc<<<"scale=3;$a*$b")

$ echo $d

1.82

<<<

<<< - это here-string передает строку на ввод команды, все преимущество в том, что используя канал для той же цели мы используе subshells, и с переменными в исходной оболочке естественно будут проблемы например:

$ echo "hello world" | read first

$ echo $first

     #встает законный вопрос: Где переменная?

И совсем другое дело с here-string

$ read first <<< "hello world"

$ echo $first

hello world

 here-string может рассматриваться как урезанная форма here document.

Еще одна справочная шпаргалка

Регулярные выражения

Регулярные выражения — гибкое и эффективное средство обработки текстов. Универсальные шаблоны регулярных выражений сами по себе напоминают миниатюрный язык программирования, предназначенный для описания и разбора текста. При дополнительной поддержке со стороны конкретной утилиты или языка программирования регулярные выражения способны вставлять, удалять, выделять и выполнять самые невероятные операции с текстовыми данными любого вида. Они бывают очень простыми, вроде команды поиска в текстовом редакторе, или очень сложными, как специализированные языки обработки текстов.На низком уровне регулярное выражение описывает некий фрагмент текста. Им можно воспользоваться для проверки данных, введенных пользователем, или, например, для фильтрации больших объемов данных. На более высоком уровне регулярные выражения позволяют управлять данными.

Регулярные выражения — абстрактная концепция, по-разному реализуемая в разных программах.

Регулярные выражения — используются в повседневной работе для решения простейших и рутинных задач.

Регулярные выражения — можно применять для фильтрации текстовых файлов или выходных данных команд и сценариев. Они представляют собой набор шаблонов, состоящих как из специальных, так и обычных символов.

Регулярные выражения — в той или иной форме используются всеми основными текстовыми редакторами и утилитами, выполняющими фильтрацию текста.

Регулярные выражения и методы работы с ними — важный аспект shell-программирования. Знакомство этой с методикой позволит повысить качество создаваемых сценариев, так как во многих случаях три-четыре команды фильтрации текста можно заменить одной командой с регулярным выражением. 

На тему «регулярные выражения» написана не мало толстых и веселых книг, справочников, одну из них можно рекомендовать к прочтению:

---> Jeffrey EF. Friedl Регулярные выражения (3 издание)


https://ru.wikibooks.org/wiki

http://habrahabr.ru/post

http://regexpstudio.com/ru/TRegExpr/Help/regexpstudio.html

http://planetcalc.ru/708/

http://easyregexp.ru/


При работе в UNIX или Linux часто используются регулярные выражения, гибкое владение которыми являет не сомненный признак профессионализма. Если, например, требуется найти слово, у которого первые два символа являются прописными буквами, а следующие четыре символа — цифрами, сформировать правильный шаблон поиска помогут регулярные выражения.

К сожалению, наборы поддерживаемых выражений несколько различаются от программы к программе, но существуют так называемые базовые регулярные выражения, которые во всех программах обрабатываются одинаково. Ниже перечислены метасимволы и операторы, применяемые в базовых регулярных выражениях.

Различные реализации регулярных выражений интерпретируют обратную косую черту перед метасимволами по-разному. Например, egrep и Perl интерпретируют скобки и вертикальную черту как метасимволы, если перед ними нет обратного слэша и воспринимают их как обычные символы, если слэш есть.

Классы и категорий символов

Многие диапазоны символов зависят от выбранных настроек локализации. POSIX стандартизовал объявление некоторых классов и категорий символов, как показано в следующей таблице:

Создание шаблонов для поиска выражений

Поиск одиночных символов с помощью метасимвола ´.´


Метасимвол '.' соответствует любому одиночному символу. Если, например, требуется найти слово, начинающееся с подстроки “beg”, после которой стоит произвольный символ, а за ним — символ 'n', задайте шаблон beg. n , Будут найдены такие слова, как “begin”, “began” и т.д.

Данный метасимвол удобно применять при фильтрации результатов работы команды Is -l для поиска файлов, имеющих требуемые права доступа. Следующий шаблон соответствует файлам, выполнять которые могут все пользователи;

...x..х..х

Пример:

$ ls -l

итого 38816

drwxr-xr-x 2 imint imint 4096 марта 21 19:26 abby

-rw-r--r--    1 imint imint 1066 июля 22 15:30 account.err

-rw-r--r--    1 imint imint 77 июля 22 15:41 accounts.err

-rw-r--r--    1 imint imint 191 июля 22 15:41 accounts.out

drwx------   4 imint imint 4096 апр. 22 12:13 Dropbox

-rw-r--r--    1 imint imint 20828 марта 21 19:39 en:download

-rwxr-xr-x  1 imint imint 93 июля 27 17:05 f_desc

-rw-r--r--    1 imint imint 834 июля 22 14:15 files.out

-rw-r--r--    1 imint imint 0 июля 22 14:21 file.zzz

-rw-r--r--    1 imint imint 0 июля 28 14:20 find

-rw-r--r--    1 imint imint 0 апр. 29 14:58 grep.cc

-rw-r--r--    1 imint imint 71 июля 22 15:23 grep.err

-rwxr-xr-x  1 imint imint 73 марта 16 17:27 ip-script

drwxrwxr-x 5 root root 4096 окт. 9 2013 loganalyzer-3.6.5

-rw-r--r--    1 root root 1046957 окт. 9 2013 loganalyzer-3.6.5.tar.gz

drwx------   2 imint imint 4096 июля 26 19:24 Mail

-rw-r--r--    1 imint imint 94 июля 27 16:39 myfile

..........................................................................................

-rw-r--r--      1 root root 21833478 дек. 31 2014 webmin_1.730_all.deb

-rw-r--r--      1 imint imint 90 июля 26 16:58 who.out

-rw-r--r--      1 imint imint 1112 окт. 27 2013 xmobar.config

-rw-r--r--      1 imint imint 1171 июля 25 19:07 xmobarrc

-rw-------       1 imint imint 588 июля 26 18:47 yes

-rw-r--r--       1 imint imint 12236800 июля 26 17:11 zz-11

drwxr-xr-x    3 imint imint 4096 марта 15 12:26 Видео

drwxr-xr-x    3 imint imint 4096 июля 20 21:20 Документы

drwxr-xr-x    2 imint imint 4096 мая 28 10:36 Загрузки

drwxr-xr-x    2 imint imint 4096 марта 10 23:05 Изображения

drwxr-xr-x    2 imint imint 4096 марта 10 23:05 Музыка

drwxr-xr-x    2 imint imint 4096 марта 10 23:05 Общедоступные

drwxr-xr-x    5 imint imint 4096 июля 20 22:01 Рабочий стол

drwxr-xr-x    2 imint imint 4096 марта 10 23:05 Шаблоны

$ ls -l | awk '{print $1 $3 $6 $7 $8 $9}'| grep  '...x..x..x' 

drwxr-xr-x  imint  марта  21  19:26  abby

-rwxr-xr-x   imint  июля  27  17:05  f_desc

-rwxr-xr-x   imint  марта  16  17:27  ip-script

drwxrwxr-xroot     окт.  9  20:13  loganalyzer-3.6.5

drwxr-xr-x  imint  июля  27  17:01  scripts

-rwxrwxr-x  imint  июля  20  21:50  test.xxx

drwxr-xr-x  imint  марта  15  12:26  Видео

drwxr-xr-x  imint  июля  20  21:20  Документы

drwxr-xr-x  imint  мая  28  10:36  Загрузки

drwxr-xr-x  imint  марта  10  23:05  Изображения

drwxr-xr-x  imint  марта  10  23:05  Музыка

drwxr-xr-x  imint  марта  10  23:05  Общедоступные

drwxr-xr-x  imint  июля  20  22:01  Рабочий

drwxr-xr-x  imint  марта  10  23:05  Шаблоны

$

В приведенном примере командная строка: $ ls -l | awk '{print $1 $3 $6 $7 $8 $9}'| grep  '...x..x..x'  Программа awk извлекает из этого списка только столбцы: 1,3,6,7,8,9, а команда grep  '...x..x..x'  применяет шаблон ...x..х..х. 

Команда $ ls -l (в первой части примера) для наглядности выполнена отдельно, вывод урезан.

Предположим, выполняется фильтрация текстового файла. Необходимо найти в нем строки, состоящие из десяти символов, из которых пятый и шестой ¨ХС¨. Данная задача решается с помощью такого шаблона:

....ХС....

Он означает:

первые четыре символа могут быть - произвольными,

следующие два - "ХС",

последние четыре - тоже произвольные.

Ниже пример сравнения:

Для наглядность создадим подобный файл:

~$ cat > XXXX

234ХС9088

4523ХХ9001

0011ХА9912

9931ХС3445 

^C

~$

234ХС9088   - несоответствует 

4523ХХ9001 - не соотв1етствует 

0011ХА9912 - не соответствует 

9931ХС3445 - соответствует

Выполним поиск:

$ cat  XXXX | grep '....ХС....'

9931ХС3445 

~$

Поиск выражений в начале строки с помощью метасимвола ¨^¨

Метасимвол '^' (крышка) позволяет искать слова или символы, стоящие в начале строки. Например, благодаря шаблону ^d можно отобрать из списка, выводимого командой Is -l, только те записи, которые соответствуют каталогам:

 $ ls -l | awk '{print $1 $9}'| grep '^d'

drwxr-xr-xabby

drwx------Dropbox

drwxrwxr-xloganalyzer-3.6.5

drwx------Mail

drwxr-xr-xscripts

drwxr-xr-xВидео

drwxr-xr-xДокументы

drwxr-xr-xЗагрузки

drwxr-xr-xИзображения

drwxr-xr-xМузыка

drwxr-xr-xОбщедоступные

drwxr-xr-xРабочий

drwxr-xr-xШаблоны

$

Вернемся к файлу XXXX, шаблон ^001 соответствует строкам, начинающимся с символов "001". Результат его применения может быть таким:

1234ХС9088 - не соответствует

4523ХХ9001 - не соответствует 

0011ХА9912 - соответствует 

9931ХС3445 - не соответствует

~$ cat  XXXX | grep '^001'

0011ХА9912

~$ 

Для поиска строк, у которых в четвертой позиции от начала стоит символ ¨1¨, можно воспользоваться следующим шаблоном:  ^...1

В результате получим:

1234ХС9088 - не соответствует

4523ХХ9001 - не соответствует 

0011XA9912 - соответствует 

9931ХС3445 - соответствует

~$ cat  XXXX | grep '^...1'

0011ХА9912

9931ХС3445 

~$ 

Чтобы найти строки, начинающиеся с символов “comp”, следует указать: ^comp

Давайте немного усложним этот шаблон. Предположим, после символов "comp" могут идти любые две буквы, но завершать последовательность должны символы "ing": ^сomp.. ing

Этот шаблон обеспечивает поиск таких слов, как "computing", "complaining" и тд., то есть в регулярном выражении можно сочетать различные шаблоны поиска.

Поиск выражений в конце строки с помощью метасимвола ¨$¨


Метасимвол "$" предназначен для поиска слов или символов, находящихся в конце строки. Он указывается в конце шаблона. Предположим, требуется найти строки, заканчивающиеся словом "trouble". Эту задачу позволяет решить такой шаблон: trouble$

Следующий шаблон соответствует пустой строке, не содержащей символов: ^$

А с помощью следующего шаблона можно найти строки, включающие только один символ: ^.$

Поиск символов, встречающихся неопределенное число раз, с помощью метасимвола "*"

Метасимвол '*' означает, что предыдущий символ в регулярном выражении либо отсутствует, либо встречается произвольное число раз подряд (1, 2 и т.д.). Например, шаблон: compu*t

отвечает таким словам:

computer

computing

compuuuuute

А шаблон: 10133*

соответствует следующему:

101333

10133

10134

Поиск специальных символов с помощью метасимвола ¨\¨

Ряд символов, попадая в состав регулярных выражений, приобретает специальное значение. В общем случае специальными являются следующие символы:  $ . ` ¨ * [ ] ^ | ( ) \ + ?

Когда требуется найти строку, содержащую один из таких символов, его необходимо "защитить" в шаблоне с помощью обратной косой черты, которая отменяет специальное значение следующего за ней метасимвола. Предположим, строка содержит символ ¨.¨ который, как известно, в регулярном выражении соответствует произвольному символу. Вот шаблон для него: \.

Если необходимо найти файлы, допустим, с расширением pas, можно применить следующий шаблон:  \*\.pas

Поиск символов, входящих в заданный набор или диапазон ¨[ ]¨

Шаблон [ ] соответствует списку или диапазону символов, указанных в квадратных скобках.

Символы в списке можно разделять запятыми. Это облегчает восприятие шаблона, хотя и не является обязательным требованием.

Для задания диапазона символов используется дефис (-). Слева от него указывается первый символ диапазона, а справа — последний. Предположим, необходимо найти символ, являющийся цифрой. Можно применить такой шаблон: [0123456789]

Однако проще задать диапазон: [0-9]

Следующий шаблон соответствует любой строчной букве: [а-z]

Чтобы найти любую букву произвольного регистра, воспользуйтесь шаблоном: [A-Za-z]

Здесь формируется список из двух диапазонов: прописные буквы от А до Z и строчные буквы от а до z.

Представленный ниже шаблон соответствует любому алфавитно-цифровому символу: [A-Za-zO-9]

Далее показан шаблон, предназначенный для поиска трех-символьных комбинаций следующего типа: в начале находится буква s, за ней может следовать любая прописная или строчная буква, а завершает последовательность буква t: s[a-zA-Z]t

Если же комбинация состоит только из букв нижнего регистра, воспользуйтесь таким шаблоном: s[a-z]t

Чтобы найти слово “computer” независимо от того, расположено оно в начале предложения или нет, примените такой шаблон: [Сс]omputer

Следующий шаблон соответствует слову “system”, которое начинается с прописной или строчной буквы и за которым следует точка: [S,s]ystem\.

Запятая в квадратных скобках поставлена для того, чтобы сделать шаблон удобным для зрительного восприятия.

Метасимвол '*' размещенный после квадратных скобок, указывает на то, что символы в скобках могут повторяться неопределенное число раз. Например, следующий шаблон соответствует любому слову: [A-Za-z]*

Метасимвол '^' после открывающей квадратной скобки — это признак того, что шаблон соответствует любым символам, кроме указанных в скобках. Так, шаблон соответствует вcем символам, кроме букв: [^a-zA-Z]

Шаблон отвечает всем символам, которые не являются числами: [^0-9]

Поиск символов встречающихся заданное число раз

Метасимвол ¨*¨ позволяет находить символы, встречающиеся несколько раз подряд, но число повторений при этом не определяется. Если же необходимо в процессе поиска учитывать точное количество последовательных вхождений символа в строку, следует применить шаблон \{ \}. Существует четыре варианта этого шаблона:

шаблон\ {n\} Соответствует шаблону, встречающемуся ровно n раз подряд

шаблон\ {n, \} Соответствует шаблону, встречающемуся не менее n раз подряд

шаблон\ {, m\} Соответствует шаблону, встречающемуся не более m раз подряд

шаблон \ {n, m\} Соответствует шаблону, встречающемуся не менее n и не более m раз подряд, где n и m — целые числа из интервала от 0 до 255

Представленный ниже шаблон соответствует последовательности из двух букв А, за которыми следует буква В: А\ {2\}В

В результате получим ¨ААВ¨.

В следующем шаблоне задано, что буква А встречается не менее четырех раз подряд: А\ {4,\}В

Возможные результаты поиска — ¨ААААВ¨ или ¨АААААААВ¨, но не ¨АААВ¨. Поиск последовательности, в которой буква А встречается от двух до четырех раз, выполняется по такому шаблону: А\ {2,4\}В

Будут найдены строки ¨ААВ¨, ¨АААВ¨, ¨ААААВ¨, но не ¨АВ¨ или ¨АААААВ¨.

Вернемся к уже рассматривавшемуся примеру фильтрации текстового файла, фрагмент которого представлен ниже:

1234ХС9088

4523ХХ9001

0011ХА9912

9931ХС3445

Допустим, требуется найти строки, в которых первые четыре символа — цифры, за ними идут символы "XX", а затем — еще четыре цифры. Решить данную задачу позволит такой шаблон: [О—9]\{4\}XX[0—9]\{4\}

Применив этот шаблон к приведенному выше фрагменту, получим:

1234ХС9088 - не соответствует

4523XX9001 - соответствует

0011ХА9912 - не соответствует

9931ХС3445 - не соответствует

Примеры:

$ cat myfile1

Привет! Я работаю за терминалом xterm

25-07-2015

мое имя imint

XX-ZZ-345.Y

1234567890

192.168.255.255

192.168.0.1

Пока!

25-12-2015

######################################

$ cat myfile1 | grep '[0-9]\{2\}-[0-9]\{2\}-[0-9]\{4\}' 

#Соответствует шаблону даты в формате ¨dd-mm-yyyy¨

25-07-2015

25-12-2015

$ cat myfile1 | grep '[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{1,\}\.[0-9]\{1,\}' 

#Соответствует шаблону IP-адреса в формате ¨nnn.nnn.n.

192.168.255.255

192.168.0.1

$