Литмир - Электронная Библиотека

Аналогичным образом будет вести себя и редактор sed при работе с данным; файлом. Если вы попытаетесь просмотреть его содержимое, будет выдано следующее:

$ sed -n '1,$p' func.txt

This is the F1 key:P This is the F2 key:Q

В редакторе существует команда l (list}, аналог рассмотренной выше команды cat -v. Формат команды l таков:

[адрес1[,адрес2]]l

Ее действие равносильно применению команды p, но при этом все непечатаемые символы заменяются восьмеричными ASCII–кодами (кроме того, длинные строки, выходящие за пределы экрана, разбиваются на части, а конец каждой строки помечается символом '$'). Вот что получится, если применить эту команду к файлу func.txt.

$ sed -n '1,$1' func.txt

This is the Fl key:\033OP$ This is the F2 key:\033OQ$

Теперь ситуация немного проясняется. По таблице ASCII–кодов можно узнать, что восьмеричный код 033 соответствует непечатаемому символу esc. Именно он в выводе команды cat -v обозначается как ^ [. За ним идут два обычных символа: сначала 'О', затем 'Р' либо 'Q'. Таким образом, мы имеем дело с двумя клавишами, каждая из которых сгенерировала трехсимвольную последовательность: одна — esc‑O–р, а вторая — esc‑o–q. Когда файл отображается в обычном режиме, каждому символу соответствует одно знакоместо, поэтому первые два символа последовательности отбрасываются и остается последний: 'P' и 'Q' соответственно.

Нет системной команды, которая позволяла бы узнать, какие клавиши генерируют эти коды. Подобные сведения находятся в базах данных termcap и terminfo, хранящих установки терминала, но знакомство с этими базами данных выходит за рамки нашей книги. Проще всего пойти экспериментальным путем: ввести команду cat или cat -v без указания входного файла, с тем чтобы попробовать самостоятельно определить, нажатия каких клавиш приводят к отображению на экране нужных последовательностей символов. В нашем случае последовательность ESC‑O–P генерируется клавишей [F1], а последовательность ESC‑O–Q — клавишей [F2], хотя в общем это зависит от установок терминала.

Если вам интересно, как можно создать файл func.txt, ниже описана возможная процедура:

   1. Загрузите редактор vi.

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

   3. Нажмите [Ctrl+V], при этом появится символ '^'

   4. Нажмите клавишу [F1], при этом отобразится последовательность [ор.

   5. Нажмите клавишу [Enter] и повторите пункты 2—4 для второй строки файла (в конце нажимается клавиша [F2]).

   6. Нажмите клавишу [Esc], чтобы выйти из режима вставки.

   7. Введите команду w func.txt, чтобы сохранить файл.

   8. Введите команду q, чтобы выйти из редактора vi.

10.16. Дополнительные примеры использования редактора sed

Выше были описаны основные команды sed. Далее мы рассмотрим ряд практических примеров применения редактора sed.

10.16.1. Обработка управляющих символов

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

$ cat -v dos.txt

12332##DISO##45.12^M C0332##LPSO##23.11^M

01299##USPD##34.46^M

Вот что необходимо сделать:

   1. Заменить все знаки решетки ('#'( пробелом.

   2. Удалить из первого поля каждой строки все ведущие нули.

   3. Удалить в конце каждой строки последовательность ^M, генерируемую непечатаемым символом CR — возврат каретки (ASCII–код 13).

Примечание:

В ряде систем, в которых мне приходилось выполнять подобные преобразования, в конце строки стоит символ перевода строки LF (ASCII–код 10, отображается как ^@). Подобная проблема нередко возникает при передаче файлов между двумя системами, в одной из которых символ новой строки (\n) заменяется последовательностью CR/LF, a в другой — только одним из этих двух управляющих символов.

Задача 1. Удаление всех символов решетки реализуется без особого труда. Для этого достаточно выполнить команду замены s с флагом глобальной подстановки д, указав при этом, что один или более символов '#', идущих подряд, должны быть заменены пробелом:

$ sed 's/##*/ /g' dos.txt | cat -v

12332 DISO 45.12^М

00332 LPSO 23.11^М

01299 USPD 34.4б^M

Задача 2. Для удаления всех ведущих нулей следует в команде s оставить шаблону замены пустым, а шаблон поиска задать таким: /^0*/. Он означает, что требуется найти любое количество нулей, стоящих в начале строки.

$ sed 's/^0*//' dos.txt | cat -v

12332##DISO##45.12^M

332##LPSO##23.11^M

1299##USPD ##34.46^M

Задана 3. Чтобы избавиться от управляющих символов ^M в конце строк, необходимо. также применить команду s, оставив шаблон замены пустым. А вот при формировании шаблона поиска следует учесть, что мы имеем дело с непечатаемым символом. Нельзя просто ввести символы '^' и 'M', так как полученный шаблон будет означать, что мы ищем букву 'М', стоящую в начале строки. Чтобы действительно создать нужный нам непечатаемый символ, необходимо нажать [Ctrl+V], а затем — клавишу [Enter]. Результат будет выглядеть как регулярное выражение ^M, но на самом деле это экранное представление символа CR.

$ sed 's/^M//' dos.txt | cat -v

12332##DIS0##45.12 0D332##LPSO##23.11 01299##U5PD#t34.46

Теперь можно попробовать объединить три команды в одну с помощью опции -e;

$ sed -e 's/^0*//' -e 's/^M//' -e 's/##*/ /g' dos.txt | cat -v

12332 DISO 45.12

332 LPSO 23.11

1299 USPD 34.46

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

Приведенные выше команды удобнее поместить в файл сценария. Назовем его dos.sed. Вот его текст:

$ cat dos.sed

#! /bin/sed -f

#Имя: dos.sed

#Командная строка: dos.sed dos.txt

#Избавляемся от символа решетки

s/##*/ /g

#Удаляем ведущие нули

s/^0*//

#Удаляем символы возврата каретки

s/^M//

На входе данного сценария следует указать файл dos.txt. Сценарий "исправит" этот файл и выведет результат на экран. Если же ввести следующую командную строку:

$ dos.sed dos.txt | tee dos.txt

то результат будет записан обратно в файл dos.txt.

10.16.2. Обработка отчетов

Я часто сталкиваюсь с необходимостью форматировать данные, возвращаемые инструкциями SQL. Для этого приходится писать комплексные сценарии, в которых сразу несколько текстовых фильтров выполняют работу совместно. Рассмотрим результаты выполнения некоторой инструкции SQL, выполняющей обращение к одной из таблиц базы данных:

Database

Size (MB)

Date created

GOSOUTH

2244 5632

12/11/9? 8/9/99

TRISUD

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

   1. Удалить пунктирную линию с помощью команды s/--*//g.

   2. Удалить все пустые строки с помощью команды /^$/d.

   3. Удалить последнюю строку с помощью команды $d.

   4. Удалить первую строку с помощью команды 1d.

   5. Отобразить первый столбец с помощью команды awk '{print $1}'. Ниже приведена соответствующая цепочка команд:

$ sed 's/--*//g' -e '/^$/d' -e '$d' -e '1d' sql.txt | awk '{print $1}'

GOSOUTH TRISUD

10.16.3. Добавление текста

37
{"b":"273485","o":1}