Шрифт:
Одной из задач, для которых редактор 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.