5. Пункты 3 и 4 повторяются до тех пор, пока во втором файле есть строки с совпадающим первым полем.
6. Пункты 2—6 повторяются для каждой строки первого файла.
Таким образом, в выходной поток попадают только строки, имеющие общие компоненты.
Общий формат команды join таков:
join [опции] входной_файл1 входной_файл2
Рассмотрим некоторые наиболее важные опции этой команды:
-a
n
Задает включение в выходной поток строк из файла n (n -l или 2), для которых не было найдено ни одного совпадения по указанному полю.
-o
формат
Задает формат выводимой строки. Параметр формат представляет собой разделенный запятыми или пробелами список спецификаций, каждая из которых, в свою очередь, имеет формат номер_файла. поле. По умолчанию формат выводимой строки таков:
1 — поле, по которому производится объединение;
2 -oставшаяся часть первой строки;
3 -oставшаяся часть второй строки.
-1
поле
Объединять строки по указанному полю первого файла (по умолчанию таковым является первое поле)
-2
поле
Объединять строки по указанному полю второго файла (по умолчанию таковым является первое поле)
-t
символ
Задает разделитель полей во входном и выходном потоках
11.3.1. Объединение двух файлов
Предположим, имеется два текстовых файла: один называется names.txt и содержит имена пользователей с указанием улиц, на которых они проживают, а другой называется town.txt и содержит имена пользователей с указанием городов, в которых они живут.
$ cat names.txt
M. Golls 12 Hidd Rd
P. Heller The Acre
P. Willey 132 The Grove
T. Norms 84 Connaught Rd
K. Fletch 12 Woodlea
$ cat town.txt
M. Golls Norwich NRD
P. Willey Galashiels GDD
T. Norms Brandon BSL
K. Fletch Mildenhall MAF
Задача состоит в таком соединении двух файлов, чтобы итоговый файл содержал имена пользователей и их полные адреса. Очевидно, что общим полем является первое. Команда join по умолчанию выполняет объединение файлов именно по первому полю.
$ join names.txt town.txt
M. Golls 12 Hidd Rd Norwich NRD
P. Willey 132 The Grove Galashiels GDD
T. Norms 6-3 Connaught Rd Brandon BSL
K. Fletch 12 Woodlea Mildenhall MAF
Как видите, пользователь P. Heller, для которого нет строки во втором файле, в результаты работы команды join не попал.
11.3.2. Включение несовпадающих строк
Если требуется все‑таки включить информацию о пользователе P. Heller в выходные данные, воспользуйтесь опцией -a. Поскольку исходная строка находится в первом файле, параметром данной опции будет цифра 1:
$ join -a1 names.txt town.txt
M. Golls 12 Hidd Rd Norwich NRD
P. Heller The Acre
P. Willey 132 The Grove Galashiels GDD
T. Norms 84 Connaught Rd Brandon BSL
K. Fletch 12 Woodlea Mildenhall MAF
В общем случае, чтобы включать в результаты несовпадающие строки из обоих файлов, применяйте команду join -a1 -a2.
11.3.3. Задание формата вывода
Опция -o позволяет указать, какие поля и в какой последовательности следует включать в формируемую строку. Допустим, нужно создать файл, который включает только имена пользователей и названия городов, в которых они проживают. Требуемая информация содержится в первом поле первого файла и втором поле второго файла. Соответствующая команда имеет следующий вид:
$ join -о 1.1,2.2 names.txt town.txt
M. Golls Norwich
P. Willey Galashiels
T. Norms Brandon
K. Fletch Mildenhall
11.3.4. Выбор ключевого поля
He всегда первое поле является общим для обоих файлов. Рассмотрим пример. Имеются два файла:
$ cat pers
P. Jones Office Runner ID897
S. Round UNIX admin ID667
L. Clip Personl Chief ID982
$ cat pers2
Dept2C ID897 6 years
Dept3S ID667 2 years
Dept5Z ID982 1 year
Файл pers содержит имена, названия должностей и личные идентификационные номера служащих фирмы. Файл pers2 содержит для каждого из служащих код отдела, в котором он работает, идентификационный номер и стаж работы на фирме. В данном случае требуется выполнить соединение строк по номеру служащего. Он хранится в четвертом поле первого файла и во втором поле второго файла. Задать их в команде join можно с помощью опции -n т, где п — номер файла, a m — номер поля.
Ниже приведена соответствующая команда и результат ее выполнения:
$ join -1 4 -2 2 pers pers2
ID897 P. Jones Office Runner Dept2C 6 years
ID667 S. Round UNIX admin Dept3S 2 years
ID982 L. Clip Personl Chief Dept5Z 1 year
При работе с командой join следует быть внимательным, вычисляя номер нужного поля. Можно посчитать, что доступ реализуется к полю 4, а с точки зрения команды join это поле 5. В итоге будут получены неправильные результаты. Чтобы проверить, содержит ли поле с указанным номером предполагаемые данные, воспользуйтесь утилитой awk:
$ awk '{print $4}' имя_файла
11.4. Вырезание текста с помощью команды cut
Команда cut позволяет вырезать фрагменты строк из текстовых файлов или из стандартного входного потока. Извлеченный подобным образом текст направляется в стандартный выходной поток. Общий формат команды cut таков:
cut [опции] файлы…
Рассмотрим основные опции этой команды:
-c список Определяет, какие символы извлекаются из каждого входного файла
-f список Определяет, какие поля извлекаются из каждого входного файла
-d Задает разделитель полей
Параметр список в опциях -c и -f представляет собой разделенный запятыми список диапазонов символов или полей соответственно. Диапазон может быть задан в одной из четырех форм:
-n В выходной поток включается каждый n–й символ (поле) каждой строки
каждого входного файла
n- Диапазон формируется от n–го символа (поля) до конца строки
n–m Диапазон формируется от n–го символа (поля) до m–го символа (поля) включительно
-m Диапазон формируется от начала строки до m–го символа (поля)
11.4.1. Задание разделителя полей
В качестве входного файла мы возьмем файл pers из предыдущего примера, только на этот раз поля в нем будут разделены двоеточием.
$ cat pers
P. Jones:Office Runner:ID897
S. Round:UNIX admin:ID667
L. Clip:Personl Chief:ID982
Предположим, необходимо извлечь из файла список идентификационных номеров служащих, находящийся в третьем поле. Вот как можно это сделать:
$ cut -d: — f3 pers
ID897
ID667
ID982
Опция -d: говорит о том, что поля в файле разделяются двоеточием. Опция -f 3 задает выборку третьего поля.
Если требуется вырезать несколько полей, необходимо перечислить их в опции -f. Например, показанная ниже команда формирует список служащих с их идентификационными номерами:
$ cut -d: — f1,3 pers
P. Jones:ID897
S. Round:ID667
L. Clip:ID982
А вот как можно извлечь из каталога /etc/passwd регистрационные имена пользователей и имена их начальных каталогов, хранящиеся в полях 1 и 6 соответственно:
$ cut -d: — f1,6 /etc/passwd
gopher:/usr/lib/gopher‑data
ftp:/home/ftp
peter:/home/apps/peter
dave:/home/apps/dave