Практическая работа №4. Использование перенаправлений и конвейера (программного канала)

Опубликовано пользователем Бессонов Л.В. 12.11.2009г.

Цель работы

Ознакомление с утилитами *nix систем.

Теоретические материалы

  1. sed - потоковый (для потока данных) текстовый редактор
  2. cut - удаление фрагмента из каждой строки
  3. paste - склейка строк файлов
  4. join - соединение файлов
  5. sort - сортировка и/или слияние файлов
  6. uniq - выдача информации о повторяющихся строках файла
  7. head - вывод первых строк файла
  8. tail - вывод последних строк файла
  9. pr - форматированный вывод

Выполнение работы

В составе операционных систем семейства *nix имеется большое число системных утилит, предназначенных для обработки текстов. Утилиты cat и grep, с которыми Вы уже познакомились, относятся к их числу. Другие утилиты такого рода: cmp - сравнение файлов, cut - "вырезание" полей из текста и paste - сцепление строк файлов, head - распечатка начала файла и tail - распечатка последних строк файла, sort - сортировка, join - объединение, sed - потоковый текстовый редактор и многие другие.

Каждая из таких утилит выполняет в принципе простую обработку текстового файла, но последовательно применяя одну утилиту за другой, можно скомбинировать их действия в таким образом, что итоговое преобразование текста будет достаточно сложным. Обработка текста при помощи последовательных вызовов системных утилит называется в *nix "фильтрацией" текста, а сами утилиты называются фильтрами. Такие названия происходят от метафорического представления прохождения потока данных через набор фильтров, каждый из которых производит отбор каких-то требуемых составляющих, в результате чего мы получаем те данные, которые нам нужны - "отфильтрованные" данные.

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

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

Имеется, однако, возможность перенаправлять стандартные потоки. Запись вида:

команда [аргументы] < файл

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

Записи вида:

команда [аргументы] > файл

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

Запись вида:

команда1 [аргументы]  | команда2 [аргументы] | ... | командаN [аргументы]

определяет конвейер или программный канал. В этом случае стандартный вывод команды1 будет перенаправлен в стандартный ввод команды2. Программный канал является наиболее популярным средствам при построении цепочек фильтрации.

В данной практической работе Вам предлагается разработать последовательности команд для решения трех задач обработки текстовых файлов. Основным инструментом для решения этих задач для Вас, по-видимому (но не обязательно), будет редактор sed и утилита соединения join. Другие средства Вы выберете сами. Однако запретим использовать в этой работе утилиту awk - ей будет посвящена отдельная работа.

Задача 1

Создайте текстовый файл с текстом (5-10 строк). Выполнить в соответствии с Вашим вариантом индивидуального задания преобразование этого текстового файла. Результат сохранить в новом файле, исходный файл должен остаться без изменения.

Задача 2

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

с которыми Вы работали в работе №3. Результат сохранить в новом файле.

Задача 3

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

Индивидуальные варианты

Вариант 1

  • В созданном текстовом файле перенести третью от конца строчку в начало файла.
  • Из информации, содержащейся в файлах query[1-5], определить отделы (название и город), которые получали заказы на общую сумму больше 1000.
  • Определить количество групп пользователей.

 Вариант 2

  • В созданном текстовом файле перенести третью от начала строку в конец файла.
  • Из информации, содержащейся в файлах query[1-5], определить города, в которых расположены отделы, выполнявшие заказы в феврале 1991г.
  • Определить количество подкаталогов в /student, к которым нет публичных прав доступа.

Вариант 3

  • В созданном текстовом файле перед каждой строкой вставить текущее время.
  • Из информации, содержащейся в файлах query[1-5], определить фамилии продавцов, которые выполняли заказы на поставку товара 'SP JUNIOR RACKET'.
  • Определить количество подкаталогов в /student, к которым есть публичные права на поиск и чтение в них.

Вариант 4

  • В созданном текстовом файле удалить вторую строку, начинающуюся с буквы 'Н'.
  • Из информации, содержащейся в файлах query[1-5], определить штат, в котором был сделан заказ на самую большую общую сумму.
  • Определить количество пользователей из вашей студенческой группы.

Вариант 5

  • В созданном текстовом файле оставить в каждой строке не более двух слов. Слова, выходящие за этот предел поместить в отдельный файл. В первом файле-результате в тех строках, которые содержат менее двух слов, в конец строки должен быть добавлен символ '='. Во втором файле-результате пустых строк оставаться не должно, а перед непустыми строками должны быть указаны их номера в исходном файле, отделенные от остального текста одним пробелом.
  • Из информации, содержащейся в файлах query[1-5], определить товар, которого было заказано наибольшее количество экземпляров в одном заказе.
  • Определить количество (не подкаталогов и не ссылок) файлов в каталоге /student.

Вариант 6

  • В созданном текстовом файле оставить в каждой строке не более 2-х слов. Остаток перенести в следующую строку. Если вторая строка в паре оказывается пустой - печатать в ней символ '='.
  • Из информации, содержащейся в файлах query[1-5], определить 5 покупателей, которые сделали заказов на наибольшую общую сумму в 1990 г.
  • Определить количество файлов или подкаталогов в корневом каталоге, к которым все имеют полные права доступа.

Вариант 7

  • В созданном текстовом файле первый символ каждой строки заменить на первый символ предыдущей строки. Первая строка остается без изменений.
  • Из информации, содержащейся в файлах query[1-5], определить названия товаров, которые продавались по минимальной цене.
  • Определить количество файлов в каталоге /etc, которые являются символическими ссылками.

Вариант 8

  • В созданном текстовом файле поменять местами два первых и два последних символа каждой строки.
  • Из информации, содержащейся в файлах query[1-5], определить фамилию продавца, который продал товара 'SP JUNIOR RACKET' на максимальную сумму в одном заказе.
  • Определить количество файлов в каталоге /etc, на которые есть более одной жесткой ссылки.

Вариант 9

  • В созданном текстовом файле поменять местами первую и последнюю строки файла.
  • Из информации, содержащейся в файлах query[1-5], определить фамилию продавца, который первым продал товар 'SP JUNIOR RACKET' в 1991 г.
  • Определить количество файлов в каталоге /etc, которые созданы не в этом году.

Вариант 10

  • В созданном текстовом файле после строк, которые заканчиваются точкой или запятой, вставить пустую строку.
  • Из информации, содержащейся в файлах query[1-5], определить названия товаров, которые первыми были выставлены в продажу.
  • Выбрать упорядоченный по алфавиту список подкаталогов в /student, к которым нет публичных прав.

Вариант 11

  • В созданном текстовом файле перенести последнее слово в каждой строке в новую строку. Для строк, состоящих из одного слова - не делать ничего.
  • Из информации, содержащейся в файлах query[1-5], определить названия товаров, которые заказывались вместе с товаром 'SP JUNIOR RACKET'.
  • Выбрать упорядоченный по алфавиту список подкаталогов в /student, к которым есть публичные права на поиск и чтение в них.

Вариант 12

  • В созданном текстовом файле перенести первое слово каждой строки в начало следующей строки.
  • Из информации, содержащейся в файлах query[1-5], определить названия товаров, которые когда-либо заказывал покупатель 'JOCKSPORTS'.
  • Выбрать упорядоченный по алфавиту список пользователей из вашей студенческой группы.

Вариант 13

  • В созданном текстовом файле во всех четных строках перенести первое слово строки в конец строки. Строки, содержащие только одно слово, не изменяются.
  • Из информации, содержащейся в файлах query[1-5], определить фамилии продавцов, которые когда-либо продавали товары по их максимальной цене.
  • Выбрать упорядоченный по алфавиту список файлов (не подкаталогов, не ссылок) в каталоге /student.

Вариант 14

  • В созданном текстовом файле во всех нечетных строках перенести последнее слово строки в начало строки. Строки, содержащие только одно слово, не изменяются.
  • Из информации, содержащейся в файлах query[1-5], определить названия товаров, на которые не было заказов в 1990 г.
  • Выбрать упорядоченный по алфавиту список файлов в каталоге /etc, на которые есть более одной жесткой ссылки.

Вариант 15

  • В созданном текстовом файле поменять местами четные строки с нечетными.
  • Из информации, содержащейся в файлах query[1-5], определить названия товаров, которые не были в продаже в 1990 г.
  • Выбрать упорядоченный по алфавиту список файлов в каталоге /etc, которые созданы не в этом году.

Требования к отчёту

Отчёт должен содержать три последовательности команд с пояснением действия каждой частной команды в цепочке, а также листинг их выполнения цепочки в целом.

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

Задание 1

Работа всех вариантов демонстрируется на обработке файла с именем Hum-Dum.txt, исходное содержимое которого показано в следующем протоколе:

student@r111wslin01 ~ $ cat Hum-Dum
Humpty-Dumpty
Set on the wall.
Humpty-Dumpty
Had a greate fall.
And all the king's horses,
And all the king's man.
Can not Humpty,
Can not Dumpty,
Humpty-Dumpty,
Dumpty-Humpty,
Set on this wall
Again.
student@r111wslin01 ~ $

Ниже приводятся некоторые общие соображения по решению задач 1-го задания.

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

  1. Определяются номера строк, к которым должны быть применены преобразования, а при необходимости - также и текст, который должен вставляться в целевой файл. Для определения применяются статические (заранее известные и заложенные в текст команд) команды потокового редактора. Результаты этого шага сохраняются в файле.
  2. Путем редактирования результатов 1-го шага динамически формируются команды sed для выполнения преобразования, содержащие адреса и тексты, определенные на 1-м шаге. Эти команды сохраняются в файле.
  3. Выполняется редактирование исходного текста командами, сохраненными на 2-м шаге.

Возможны два подхода к получению номеров строк, подлежащих преобразованию:

  • выполнить нумерование всех строк исходного файла (это можно сделать командой pr или командой cat с опцией -n), а затем из пронумерованной последовательности строк выбрать строку, предназначенную для обработки с ее номером; такой прием применен в решениях для вариантов 1 и 2;
  • выбрать номер строки, предназначенной для обработки, при помощи команды sed "="; такой прием применен для варианта 3.

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

 

Задание 1, вариант 1

Каждое второе слово каждой строки вывести в отдельную следующую строку. Если в строке только одно слово, ничего не делать.

Решение:
pr -n' ' -T Hum-Dum.txt |  
Вывести файл без заголовка и лишних строк, но с номерами строк.
sed -n 's/^ *//p' |  
Удалить головные пробелы.
cut -f1,3 -d' ' |  
Вырезать номер и 2-е слово.
sed -n '/[^0-9]/p' >temp01  
Удалить строки, содержащие только номер, результат сохранить в 1-м временном файле.
cut -f1 -d' ' temp01 |  
Выбрать из 1-го временного файла номера строк.
sed -n 's/$/a\\/p' >temp02  
Добавить к ним 'a\' и сохранить во 2-м временном файле.
cut -f2 -d' ' temp01 >temp03  
Выбрать из 1-го временного файла слова и сохранить в 3-м временном файле.
paste -d'\n' temp02 temp03 >temp01  
Сцепить построчно 2-й и 3-й временные файлы, вставив между сцепляемыми строками перевод строки. Результат сохранить в 1-м временном файле. Результат - набор команд sed на вставку.
sed -f temp01 Hum-Dum.txt >result  
Выполнить команды из 1-го временного файла, сохранить результат.
rm -f temp*  
Удалить временные файлы.

Протокол выполнения:

student@r111wslin01 ~ $ pr -n' ' -T Hum-Dum.txt |
> sed -n 's/^ *//p' |
> cut -f1,3 -d' ' |
> sed -n '/[^0-9]/p' >temp01
student@r111wslin01 ~ $ cut -f1 -d' ' temp01 |
> sed -n 's/$/a\\/p' >temp02
student@r111wslin01 ~ $ cut -f2 -d' ' temp01 >temp03
student@r111wslin01 ~ $ paste -d'\n' temp02 temp03 >temp01
student@r111wslin01 ~ $ sed -f temp01 Hum-Dum.txt >result
student@r111wslin01 ~ $ rm -f temp*
student@r111wslin01 ~ $ cat result
Humpty-Dumpty
Set on the wall.
on
Humpty-Dumpty
Had a greate fall.
a
And all the king's horses,
all
And all the king's man.
all
Can not Humpty,
not
Can not Dumpty,
not
Humpty-Dumpty,
Dumpty-Humpty,
Set on this wall
on
Again.
student@r111wslin01 ~ $

Обратите внимание на то, что в вышеприведенном протоколе некоторые приглашения системы выглядят как "$", а некоторые - как ">". Система печатает приглашение ">" (вторичное приглашение), если предыдущая команда заканчивается признаком конвейера "|" и, следовательно, обязательно ожидается ввод следующей команды. В противном случае печатается первичное приглашение - "$". Символы первичного и вторичного приглашения определяются переменными окружения PS1 и PS2 соответственно.

Задание 1, вариант 2

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

Решение:
pr -n' ' -T Hum-Dum.txt |  
Вывод с нумерацией строк.
cut -c7 |  
Выделение 1-го символа.
sed -n '2,$p' >temp01  
Удаление 1-й строки, символ из нее никуда не подставляется. 1-е символы строк сохраняются во временном файле.
pr -n' ' -T Hum-Dum.txt |  
Вывод с нумерацией строк.
sed -n 's/^[ ]*//p' |  
Удаление головных пробелов.
cut -f1 -d' ' |  
Вывод только столбца номеров.
paste -d' ' - temp01 |  
Сцепление номера строки (входной поток) с 1-м символом следующей строки (временный файл). Получается, например: '3 H'.
sed '$d' |  
Удаление последней строки - в нее ничего не подставляется.
sed -n 's/ /s\/\^\.\//p' |  
Замена пробела между номером и символом на служебные символы. Получается: '3s/^./H'.
sed -n 's/$/\//p' >temp01  
Добавление служебных символов в конец строки. Получается: '3s/^./H/' - команда sed на изменение 1-го символа строки. (Обратите внимание: эта команда не заканчивается флагом 'p'.) Команды сохраняются во временном файле.
sed -f temp01 Hum-Dum.txt >result  
Временный файл используется как командный скрипт sed. (Обратите внимание: если бы в командах скрипта не было бы флага 'p', а в данной команде не было бы опции -n, не вывелась бы последняя строка, для которой нет подстановки в скрипте). Результат сохраняется.
rm -f temp*  
Удаление временного файла.

Протокол выполнения:

student@r111wslin01 ~ $ pr -n' ' -T Hum-Dum.txt |
> cut -c7 |
> sed -n '2,$p' >temp01
student@r111wslin01 ~ $ pr -n' ' -T Hum-Dum.txt |
> sed -n 's/^[ ]*//p' |
> cut -f1 -d' ' |
> paste -d' ' - temp01 |
> sed '$d' |
> sed -n 's/ /s\/\^\.\//p' |
> sed -n 's/$/\//p' >temp01
student@r111wslin01 ~ $ sed -f temp01 Hum-Dum.txt >result
student@r111wslin01 ~ $ rm -f temp*
student@r111wslin01 ~ $ cat result
Sumpty-Dumpty
Het on the wall.
Humpty-Dumpty
Aad a greate fall.
And all the king's horses,
Cnd all the king's man.
Can not Humpty,
Han not Dumpty,
Dumpty-Dumpty,
Sumpty-Humpty,
Aet on this wall
Again.
student@r111wslin01 ~ $

Задание 1, вариант 3

В предпоследней строке, которая заканчивается точкой, поменять местами первое слово с последним.

Решение:
sed -n '/\.$/=' Hum-Dum.txt |  
Вывод номеров всех строк, которые заканчиваются точкой.
tail -2 |  
Вывод двух последних из этих номеров.
head -n1 > temp01  
Вывод первого из двух последних номеров. Сохранение в temp01.
sed -n 's/$/s\/ \.\*\/\/p/p' temp01 >temp02  
Формирование команды sed на вывод 1-го слова строки с номером, сохраненным в temp01. Команда сохраняется в temp02.
sed -n -f temp02 Hum-Dum.txt >temp03  
Выполнение команды из temp02, запись 1-го слова в temp03.
sed -n 's/$/s\/\[\^ \]\* \/\/gp/p' temp01 >temp02  
Формирование команды sed на вывод последнего слова строки с номером, сохраненным в temp01. Команда сохраняется в temp02.
sed -n -f temp02 Hum-Dum.txt >temp04  
Выполнение команды из temp02, запись последнего слова в temp04.
paste -d' ' temp01 temp03 |  
Сцепление через пробел номера строки и последнего слова строки.
sed -n 's/ /s\/\ [\^ \]\*$\/ /p' |  
Формирование команды sed на замену в строке с номером, выбранным из temp01, 1-го слова на текст, выбранный из temp03.
sed -n 's/$/\//p' >temp03  
Завершение формирование команды и сохранение ее в temp03.
paste -d' ' temp01 temp04 |  
Сцепление через пробел номера строки и 1-го слова строки.
sed -n 's/ /s\/\^\[\^ \]\* \//p' |  
Формирование команды sed на замену в строке с номером, выбранным из temp01, последнего слова на текст, выбранный из temp04.
sed -n 's/$/ \//p' >temp04  
Завершение формирование команды и сохранение ее в temp04.
sed -f temp03 Hum-Dum.txt |
Выполнение для исходного файла команды из temp03.
sed -f temp04 >result  
Выполнение для того, что получилось, команды из temp04.
rm -f temp*  
Удаление временных файлов.

Протокол выполнения:

student@r111wslin01 ~ $ sed -n '/\.$/=' Hum-Dum.txt |
> tail -2 |
> head -n1 > temp01
student@r111wslin01 ~ $ sed -n 's/$/s\/ \.\*\/\/p/p' temp01 >temp02
student@r111wslin01 ~ $ sed -n -f temp02 Hum-Dum.txt >temp03
student@r111wslin01 ~ $ sed -n 's/$/s\/\[\^ \]\* \/\/gp/p' temp01 >temp02
student@r111wslin01 ~ $ sed -n -f temp02 Hum-Dum.txt >temp04
student@r111wslin01 ~ $ paste -d' ' temp01 temp03 |
> sed -n 's/ /s\/\ [\^ \]\*$\/ /p' |
> sed -n 's/$/\//p' >temp03
student@r111wslin01 ~ $ paste -d' ' temp01 temp04 |
> sed -n 's/ /s\/\^\[\^ \]\* \//p' |
> sed -n 's/$/ \//p' >temp04
student@r111wslin01 ~ $ sed -f temp03 Hum-Dum.txt |
> sed -f temp04 >result
> student@r111wslin01 ~ $ rm -f temp*
student@r111wslin01 ~ $ cat result
Humpty-Dumpty
Set on the wall.
Humpty-Dumpty
Had a greate fall.
And all the king's horses,
man. all the king's And
Can not Humpty,
Can not Dumpty,
Humpty-Dumpty,
Dumpty-Humpty,
Set on this wall
Again.
student@r111wslin01 ~ $

Задание 2

Работа всех вариантов этого задания происходит на наборе файлов query[1-5]. В содержимом этих файлов легко видится регулярность структуры. Это содержимое представляют собой таблицы (реляционные таблицы) и составляют как бы базу данных, схема которой показана ниже:

Варианты задания 2 представляют собой задания на выборку данных из "таблиц" этой "базы данных". Утилиты *nix предоставляют в наше распоряжение следующие средства, которые в той или иной мере могут служить аналогом реляционных операций:

  • Операция проекции может быть осуществлена вырезанием определенных полей строки - командой cut.
  • Операция ограничения может быть осуществлена какой-либо из утилит, осуществляющих поиск строки по шаблону - grep или sed.
  • Операция естественного соединения может быть осуществлена утилитой join. Следует однако помнить, что для применения утилиты join таблицы должны быть отсортированы по тому столбцу, по которому происходит соединение, это можно сделать при помощи утилиты sort.
  • Дубликаты в файлах-таблицах могут быть устранены при помощи утилиты uniq или утилиты sort с опцией -u. Следует иметь в виду, что в первом случае дубликатами считаются совпадения полных строк, а во втором - только тех полей, по которым выполняется сортировка.
  • Рассматриваемые нами утилиты не предоставляют тех возможностей, которые предоставляют агрегатные функции SQL, однако функции MAX() и MIN() можно промоделировать, выполнив сортировку таблицы и выбрав затем первую (утилита head) или последнюю (утилита tail) строку.

В пояснениях к нашим примерам выполнения мы часто используем терминологию реляционных операций.

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

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

Задание 2 вариант 1

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

Решение:
sed 's/ \{1,\}/\:/g' ../metod/query5 |  
Установка в файле query5 разделителя ":".
cut -f1,2 -d':' |  
Проекция по номеру пункта и номеру заказа.
sort +0 -1 -t':' -n |  
Числовая (опция -n) - сортировка по номеру пункта.
sed '/^[1-4]:/d' >temp01  
Удаление тех строк, в которых номер пункта 1-4.
sort +1 -2 -t':' >temp01  
Сортировка по номеру заказа. Результат сохраняется в temp01.
sed 's/ \{1,\}/\:/g' ../metod/query4 |  
Установка в файле query4 разделителя ":".
cut -f1,2 -d':' |  
Проекция по номеру заказа и фамилии продавца.
sort +0 -1 -t':' |  
Сортировка по номеру заказа.
join -j1 1 -j2 2 -t':' - temp01 |  
Соединение с сохраненным в temp01.
cut -f2 -d':' |  
Проекция по фамилии продавца.
sort +0 -1 -t':' -u >result  
Сортировка по фамилии продавца с устранением дубликатов.
rm -f temp*  
Удаление временного файла.

Протокол выполнения:

student@r111wslin01 ~ $ sed 's/ \{1,\}/\:/g' ../metod/query5 |
> cut -f1,2 -d':' |
> sort +0 -1 -t':' -n |
> sed '/^[1-4]:/d' |
> sort +1 -2 -t':' >temp01
student@r111wslin01 ~ $ sed 's/ \{1,\}/\:/g' ../metod/query4 |
> cut -f1,2 -d':' |
> sort +0 -1 -t':' |
> join -j1 1 -j2 2 -t':' - temp01 |
> cut -f2 -d':' |
> sort +0 -1 -t':' -u >result
student@r111wslin01 ~ $ rm -f temp*
student@r111wslin01 ~ $ cat result
DUNCAN
ROSS
SHAW
TURNER
WARD
student@r111wslin01 ~ $

Задание 2, вариант 2

Определить покупателей, которые ничего не покупали в феврале 1990 г.

Решение:
cut -f1,2 -d':' ../metod/query2 |  
Проекция по коду и имени покупателя.
sort +0 -1 -t':' >temp01  
Сортировка по коду, сохранение.
sed 's/ \{1,\}/\:/g' ../metod/query4 |  
Установка разделителя ':'.
cut -f3,4 -d':' |  
Выделение кода покупателя и даты.
sed -n '/-FEB-91/p' |  
Ограничение по дате.
sort +0 -1 -t':' -u |  
Сортировка по коду покупателя, ликвидация дубликатов кодов.
join -j1 1 -j2 1 -t':' -a2 - temp01 |  
Соединение по коду покупателя (правое внешнее).
sed -n '/^[^:]*:[^:]*$/'p |  
Выборка тех строк, в которых только один раз встречается разделитель полей, то есть, нет даты.
cut -f2 -d':' |  
Проекция по имени покупателя.
sort +0 -1 >result  
Сортировка по имени.
rm -f temp*  
Удаление временных файлов.

Протокол выполнения:

student@r111wslin01 ~ $ cut -f1,2 -d':' ../metod/query2 |
> sort +0 -1 -t':' >temp01
student@r111wslin01 ~ $ sed 's/ \{1,\}/\:/g' ../metod/query4 |
> cut -f3,4 -d':' |
> sed -n '/-FEB-91/p' |
> sort +0 -1 -t':' -u |
> join -j1 1 -j2 1 -t':' -a2 - temp01 |
> sed -n '/^[^:]*:[^:]*$/'p |
> cut -f2 -d':' |
> sort +0 -1 >result
student@r111wslin01 ~ $ rm -f temp*
student@r111wslin01 ~ $ cat result
AL AND BOB'S SPORTS
AL'S PRO SHOP
ALL SPORT
AT BAT
BOB'S FAMILY SPORTS
BOB'S SWIM, CYCLE, AND RUN
CENTURY SHOP
EVERY MOUNTAIN
FAST BREAK
GOOD SPORT
HIT, THROW, AND RUN
HOOPS
JOCKSPORTS
JOE'S BIKE SHOP
JUST BIKES
JUST TENNIS
POINT GUARD
REBOUND SPORTS
SHAPE UP
STADIUM SPORTS
THE ALL AMERICAN
THE COLISEUM
THE OUTFIELD
THE POWER FORWARD
THE TOUR
TKB SPORT SHOP
VELO SPORTS
WHEELS AND DEALS
WOMENS SPORTS
student@r111wslin01 ~ $
Задание 2, вариант 3

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

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

Хотя все выбираемые данные находятся в одной таблице, нам необходимо будет применить здесь автосоединение - соединение таблицы с самой собой.

Решение:
sed 's/ \{1,\}/\:/g' ../metod/query1 >temp01  
Установка разделителя ':' в файле query1 (просто для удобства). Сохранение в temp01.
sed -n '/:PRESIDENT:/p' temp01 >temp02  
Выделение строки президента. Сохранение в temp02.
sed '/:PRESIDENT:/d' temp01 |  
Удаление строки президента.
cut -f4,6,7 -d':' temp01 >temp03  
Выделение полей фамилии, названия отдела, города. Сохранение в temp03.
cut -f6 -d':' temp02 >temp01  
Выделение названия отдела в строке президента. Сохранение в temp01.
sort +1 -2 -t':' temp03 |  
Сортировка остальных служащих по полю названия отдела.
join -j1 2 -j2 1 -t':' - temp01 |  
Соединение с названием отдела президента, сохраненным в temp01.
cut -f2 -d':' |  
Выделение из результата фамилий служащих.
sort +0 -1 -t':' >temp04  
Сортировка фамилий и сохранение их в temp04.
cut -f7 -d':' temp02 >temp01  
Выделение города в строке президента. Сохранение в temp01.
sort +2 -3 -t':' temp03 |  
Сортировка остальных служащих по полю города.
join -j1 3 -j2 1 -t':' - temp01 |  
Соединение с городом президента, сохраненным в temp01.
cut -f2 -d':' |  
Выделение из результата фамилий служащих.
sort +0 -1 -t':' |  
Сортировка фамилий.
join -j1 1 -j2 1 - temp04 >result  
Соединение тех, у кого совпадает отдел, с теми, у кого совпадает город. Результат сохраняется.
rm -f temp*  
Удаление временных файлов.

Протокол выполнения:

student@r111wslin01 ~ $ sed 's/ \{1,\}/\:/g' ../metod/query1 >temp01
student@r111wslin01 ~ $ sed -n '/:PRESIDENT:/p' temp01 >temp02
student@r111wslin01 ~ $ sed '/:PRESIDENT:/d' temp01 |
> cut -f4,6,7 -d':' temp01 >temp03
student@r111wslin01 ~ $ cut -f6 -d':' temp02 >temp01
student@r111wslin01 ~ $ sort +1 -2 -t':' temp03 |
> join -j1 2 -j2 1 -t':' - temp01 |
> cut -f2 -d':' |
> sort +0 -1 -t':' >temp04
student@r111wslin01 ~ $ cut -f7 -d':' temp02 >temp01
student@r111wslin01 ~ $ sort +2 -3 -t':' temp03 |
> join -j1 3 -j2 1 -t':' - temp01 |
> cut -f2 -d':' |
> sort +0 -1 -t':' |
> join -j1 1 -j2 1 - temp04 >result
student@r111wslin01 ~ $ rm -f temp*
student@r111wslin01 ~ $ cat result
CLARK
KING
MILLER
student@r111wslin01 ~ $

Задание 3

Источником входных данных для всех вариантов этого задания может быть команда печати содержимого каталогов ls или команда поиска файлов find. Выходной поток первой команды направляется в конвейер, где он может последовательно обрабатываться командами обработки текстов: grep, sed, cut, sort и т.п. Если в задании требуется подсчитать число элементов, в последнем звене конвейера может быть применена команда wc.

При выполнении задания следует иметь в виду, что пользовательские группы в системе совпадают с кодами студенческих групп (например: "ap109", "ap070b" и т.д.), все коды начинаются с букв "ap"; а имена пользователей формируются как: имя_группыnn, где nn - порядковый номер в группе.

Задание 3 вариант

Определить общее количество студенческих групп.

Решение:
ls -ld ../* | 
Команды выполняются из домашнего каталога пользователя - /home/имя_пользователя, а информацию о созданных для групп каталогах можно получить из каталога /home/, который может адресоваться из текущего каталога как: ../. Выводим информацию о содержимом этого каталога. Опция -l указывается, чтобы получить полную информацию, включая группу, опция -d предотвращает обход подкаталогов. Печать команды ls перенаправляется в поток.
grep "^d.\{24\}ap" | 
Признак подкаталога - буква "-d" в первой позиции выдачи команды ls, а имена групп начинаются c 25-й позиции выдачи. Команде grep задается шаблон, который определяет признак каталога в 1-й позиции и имя группы, начинающееся с букв "ap".
sed -n 's/[ ]\{2,\}/ /gp' |
Поскольку дальше потребуется выделять поля, избавимся от множественных пробелов с помощью команды sed.
cut -f4 -d ' ' | 
Выделяется 4-е поле, содержащее имя группы.
sort |
Результат сортируется, это понадобится для следующей команды. Поскольку сейчас в тексте остался только один столбец, никаких опций для сортировки мы не указываем.
uniq | 
Одна и та же группа повторяется для многих каталогов, поэтому следует избавиться от повторяющихся строк.
wc -l
Команда wc подсчитывает число оставшихся строк, результат выводится на печать.

Протокол выполнения:

student@r111wslin01 ~ $ ls -lad ../* | grep "^d.\{24\}ap" | sed -n 's/[ ]\{2,\}/ /gp' | cut -f4 -d ' ' |
> sort +0 -1 | uniq | wc -l
      3
student@r111wslin01 ~ $

Задание 3 вариант 2

Определить файлы в каталоге /etc, которые являются символическими ссылками. Вывести имена файлов и имена тех файлов, на которые они ссылаются, упорядочив список по первому имени.

Решение:
ls -ld /etc/* |
Выводится информация о содержимом интересующего нас каталога. Печать команды ls перенаправляется в поток.
grep "^[l]" | 
Выделяются те строки, которые имеют в 1-й позиции букву "l" - признак мягкой ссылки.
sort +8 -9 | 
Выполняется сортировка по 9-му столбцу - имени файла
sed -n 's/[ ]\{2,\}/ /gp' | 
Множественные пробелы заменяются одним пробелом.
cut -f9-100 -d' '
Выделяются поля, начиная с 9-го - и до конца.

Протокол выполнения:

student@r111wslin01 ~ $ ls -ld /etc/* | grep "^[l]" | sort +8 -9 | sed -n 's/[ ]\{2,\}/ /gp' | cut -f9-100 -d' '
/etc/grub.conf -> ../boot/grub/grub.conf
/etc/init.d -> rc.d/init.d
/etc/rc -> rc.d/rc
/etc/rc0.d -> rc.d/rc0.d
/etc/rc1.d -> rc.d/rc1.d
/etc/rc2.d -> rc.d/rc2.d
/etc/rc3.d -> rc.d/rc3.d
/etc/rc4.d -> rc.d/rc4.d
/etc/rc5.d -> rc.d/rc5.d
/etc/rc6.d -> rc.d/rc6.d
/etc/rc.local -> rc.d/rc.local
/etc/rc.sysinit -> rc.d/rc.sysinit
/etc/rmt -> ../sbin/rmt
student@r111wslin01 ~ $
Прикрепленный файлРазмер
er.gif5.97 кб

Баннер SGU.RU