Практическая работа №4
Работа с текстовыми файлами
Цель – знакомство с командами, работающими с текстовыми файлами
Характеристика рассмотренных в работе команд и примеры их использования
Команда-фильтр grep: поиск строки по файлам
Команда grep – одна из самых полезных и часто используемых. Она столь же важна для нахождения файлов с нужным содержимым, как ls -- для нахождения файлов с нужным именем. Поэтому стоит хорошо освоить grep -- умелое владение ей позволяет сэкономить массу времени и сил. Кроме того, регулярные выражения широко используются во многих других программах.
Часто возникает задача: надо найти, в каком файле встречается некое слово или фраза. Для этого служит команда "grep". Она ищет "образец" в указанных файлах (или в стандартном вводе, если файлы не указаны) и печатает все строки, в которых он встречается. То есть, она предназначена для поиска строк, соответствующих шаблону, заданному в параметре Шаблон. Каждая найденная строка записывается в стандартный поток вывода.
В шаблоне (образце поиска) могут быть указаны специальные символы *, ^, ?, [, ], \(, \), \{, или \}. Например, для поиска строк в файле pgm.s, начинающихся с любой буквы в любом регистре, введите:
grep "^[a-zA-Z]" pgm.s
Нажмите Enter.
Появится список строк файла pgm.s, которые начинаются с какой-либо буквы.
Вообще-то, образец поиска для grep -- это не просто строка, а так называемое "регулярное выражение", некоторые символы в котором приобретают специальное значение:
"." означает "любой символ".
"*" -- любое количество повторений (0 и больше) предшествующего символа.
"^" -- начало строки.
"$" -- конец строки.
Специальное значение имеют также символы ?, [, ], {, }, |, + , \.
Поскольку большинство этих символов имеют специальное значение и для оболочки, то образец следует указывать в одинарных кавычках (прямых апострофах).
Для просмотра всех строк файла sort.c, которые не совпадают с шаблоном, введите:
grep -v bubble sort.c
Нажмите Enter.
Появится список строк файла sort.c, не содержащих слова bubble.
Для просмотра всех строк вывода команды ls, которые содержат слово staff, введите:
ls -l | grep staff
Нажмите Enter.
Пример (найти строку "no"):
grep no *
errs:/bin/ls: file10: No such file or directory
errs:/bin/ls: file11: No such file or directory
proverbs:Dead men tell no tales.
Каждая строка предваряется именем файла, в котором она найдена, и двоеточием; если указан только один файл (или стандартный ввод), то этого не делается -- просто печатается найденная строка.
С ключом "-i" grep ищет, не различая маленькие/заглавные буквы:
Пример (найти все символьные линки в директории /etc):
ls -l /etc | grep '^l'
lrwxrwxrwx 1 root root 21 Dec 9 20:55 initrunlvl -> ../var/run/initrunlvl
lrwxrwxrwx 1root root 38 Dec 9 21:04 localtime -> ../usr/share/zoneinfo/Asia/Novosibirsk
lrwxrwxrwx 1 root root 11 Dec 9 20:44 rmt -> ../sbin/rmt*
Здесь используется то, что для символьных линков ls первым символом строки (тип файла) выводит букву "l".
Если результат grep слишком большой и не помещается на экран, то его можно "переправить" команде просмотра, например, more. Пример (показать список всех поддиректорий из директории /usr/lib):
ls -l /usr/lib | grep '^d' | more
Вообще говоря, в конвейере может участвовать сколько угодно команд. Так, команда
ls -l /usr/doc | grep '^d' | grep 'lib' | more
делает почти то же, что и в предыдущем примере, но отбирает только те директории, в имени которых есть "lib".
Сравнение файлов (команда diff)
Команда diff предназначена для сравнения текстовых файлов. С ее помощью можно сравнивать как отдельные файлы, так и содержимое каталогов.
Если в качестве параметров команды diff заданы обычные файлы, расположенные в различных каталогах, то результат работы команды diff - список несовпадающих строк.
Например, для сравнения двух файлов введите:
diff chap1.bak chap1
Нажмите Enter.
Появится список несовпадающих строк файлов chap1.bak и chap1.
Например, для сравнения двух файлов с игнорированием пробелов введите:
diff -w prog.c.bak prog.c
Нажмите Enter.
В этом случае, если две строки будут отличаться только числом пробелов и табуляций между словами, команда diff -w будет считать их одинаковыми.
Подсчет числа слов, строк и байт в файле (команда wc)
По умолчанию команда wc подсчитывает число строк, слов и байт в файлах, указанных в параметре Файл. Если параметр Файл не задан, то данные читаются из стандартного потока ввода. Результат работы команды записывается в стандартный поток вывода и в нем указывается суммарное число строк, слов и байт во всех заданных файлах. Флаги команды определяют порядок вывода. Под словом понимается символьная строка, отделенная пробелом, символом табуляции или символом новой строки.
Если в команде заданы имена файлов, то эти имена выводятся вместе с результатом подсчета.
Например, для подсчета числа строк, слов и байт в файле с именем chap1 введите:
wc chap1
Нажмите Enter.
Появится число строк, слов и байт в файле chap1.
Например, для подсчета только числа слов и байт введите:
wc -cw chap*
Нажмите Enter.
Появится число байт и слов для каждого файла, имя которого начинается с символов chap, и общий результат.
Потоковый редактор sed
Команда имеет формат:
sed [ -n ] [ -e script ] [ -f sfile ] [ files ]
Команда копирует файлы (по умолчанию со стандартного входа) на стандартный выход, редактирует их в соответствии со своими(!) командами, размещенными в "script" (в командном файле или строке редактора [а не shell!]). По флагу "-f" берет берет файл команд из файла "sfile"; Если есть только опция "-e script", то флаг "-e" можно опустить. Флаг "-n" подавляет вывод (происходящий по умолчанию). "script" состоит из команд редактирования, по одной в строке, имеющих формат:
[ addr [ , addr ] ] cmd [ args ]
"sed" циклически преобразует входные строки в выходные.
Адреса "[ addr [ , addr ] ]" – это либо номера строк, либо последняя строка (символ "$"), либо регулярные выражения в стиле редактора "ed":
"\" используется в многострочных командах для экранирования продолжения строки.
"." совпадает с любым символом.
Если адреса не указаны - просматриваются все входные строки.
Если один адрес, то выбираются совпадающие строки.
Если заданы два адреса, выбираются строки в заданном интервале.
"!cmd" выполняется команда "cmd", для строк, которые не были выбраны по адресам.
Для следующих (основных) функций (команд) максимальное число допустимых адресов указано в скобках.
(1)a\ text Добавляет text после указанной строки
Команда:
who
Результат:
root tty1 Mar 13 17:23
mas tty2 Mar 13 18:50
sae tty6 Mar 13 17:24
sae tty5 Mar 13 17:24
Пример:
who | sed '2a\
новая строка'
Результат:
root tty1 Mar 13 17:23
mas tty2 Mar 13 18:50
новая строка
sae tty6 Mar 13 17:24
sae tty5 Mar 13 17:24
(2)c\ text Удаляет выбранные строки и заменяет их на "text'.
Пример:
who | sed '/sae/ c\
cтрока замены'
Результат:
root tty1 Mar 13 17:23
mas tty2 Mar 13 18:50
строка замены
строка замены
(2)d Удаляет найденные строки
Пример:
who | sed '2,4d'
Результат:
root tty1 Mar 13 17:23
(1)i\ text Вставляет "text" на место выбранной строки. (сравните с "a\")
Пример:
who | sed '2i\
новая строка'
Результат:
root tty1 Mar 13 17:23
новая строка
mas tty2 Mar 13 18:50
sae tty6 Mar 13 17:24
sae tty5 Mar 13 17:24
(2)p Выводит найденные строки (используется с флагом "-n").
(1)q Выходит из "sed".
(2)r rfile Читает файл "rfile" и выдает на выход.
(2)s/reg_expr/rpl/flags Заменяет регулярное выражение "reg_expr" на "rpl" с учетом флагов "flags":
g |
глобально (по всей строке) |
p |
выводить замены |
w wfile |
сохранять заменяемое в "wfile". |
Пример:
who | sed 's/t/T/'
echo
who | sed 's/t/T/g'
Результат:
rooT tty1 Mar 13 17:23
mas Tty2 Mar 13 18:50
sae Tty6 Mar 13 17:24
sae Tty5 Mar 13 17:24
rooT TTy1 Mar 13 17:23
mas TTy2 Mar 13 18:50
sae TTy6 Mar 13 17:24
sae TTy5 Mar 13 17:24
(2)y/str1/str2/ Заменяет все вхождения символов "str1" соответствующими символами "str2". Длины строк должны быть одинаковыми.
Пример:
who | sed 'y/sae/SAE/'
Результат:
root tty1 MAr 13 17:23
mAS tty2 MAr 13 18:50
SAE tty6 MAr 13 17:24
SAE tty5 MAr 13 17:24
(2)! Cmd Команда(ы) "cmd" применяются к невыбранным строкам.
Пример:
who | sed '2,4!d'
Результат:
mas tty2 Mar 13 18:50
sae tty6 Mar 13 17:24
sae tty5 Mar 13 17:24
(1)= Выдает номера строк.
Пример:
who | sed =
Результат:
1
root tty1 Mar 13 17:23
2
mas tty2 Mar 13 18:50
3
sae tty6 Mar 13 17:24
4
sae tty5 Mar 13 17:24
(2){ } Скобки группируют команды.