Запросто собираем базу данных при помощи команд Linux

от автора

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

Базу данных какого рода можно собрать в Linux

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

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

Какими инструментами можно воспользоваться?

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

  • grep обеспечивает поиск по вводимой информации и позволяет выбрать те строки, которые соответствуют одному или нескольким шаблонам.

  • cut извлекает избранные фрагменты каждой строки и записывает их в стандартный вывод.

  • awk — более мощный язык для сканирования и обработки паттернов.

  • sort выполняет именно сортировку (как и следовало ожидать), но может сортировать данные и по конкретным столбцам, а также корректно справляется с числовой/алфавитной сортировкой.

  • При помощи команд head и tail можно извлекать из вывода заданный срез строк.

  • join поддерживает взаимосвязанные данные, расположенные во множестве файлов.

У вас есть инструментарий Linux — как с его помощью создать и использовать базу данных

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

Создание таблиц в виде двумерных файлов

Один из простейших структурированных текстовых форматов называется DSV или  значения, разделённые разделителем. Это более общий случай формата CSV —значений, разделённых запятыми. В структурированных текстовых файлах под Linux в качестве разделителя полей часто используются пробел или двоеточие. Классический пример — файл  /etc/passwd:

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

Buy milk:2024-10-21:2:open Call bank:2024-10-20:1:closed

Для обновления базы данных подойдёт любой текстовый редактор — в этом заключается ещё одно достоинство обычного текста. Можно добавлять элементы непосредственно из командной строки, перенаправляя вывод из echo в файл:

echo "Take out the trash:$(date -I):3:open" > tasks

Вот эквивалентный код на SQL:

INSERT INTO tasks VALUES('Take out the trash', CURDATE(), '3', 'open')

Обратите внимание: для получения актуальной даты в этой команде используется подкоманда. Немного неудобно прописывать её руками, значительно удобнее было бы автоматизировать её при помощи скрипта.

Выборка целой таблицы

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

SELECT * FROM tasks

Такой командой мы извлекаем все столбцы базы данных на высоту всех строк. Если мы имеем дело с файловой базой данных, то эквивалентная команда также тривиальна:

cat tasks

Выбор столбцов при помощи cut

Чуть более искусная операция — сузить выборку до конкретных столбцов. Вот как это делается в SQL:

SELECT task FROM tasks

При помощи инструмента cut можно реализовать практически тот же самый функционал:

cut -d':' -f1 tasks

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

Выбор строк при помощи grep или awk

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

SELECT * FROM tasks WHERE status=open

В данном случае grep отлично нам подойдёт. Воспользовавшись этой командой, можно сравнивать строки с шаблоном, заданным в виде регулярного выражения. Таким образом можно найти, например, все задачи, имеющие статус «open» (открыта):

grep 'open$' tasks

В данном случае мы опираемся на тот факт, что каждая строка оканчивается полем «status»; знак $ — это конец строки. Что касается полей в середине строки, для их обработки может потребоваться более сложное регулярное выражение. Например, вот как можно получить все строки с приоритетом 2:

grep ':2:[^:]*$' tasks

Но grep обеспечивает сопоставление только с текстовыми шаблонами и не справляется с более сложными выражениями, например, с такими:

SELECT status, task FROM tasks WHERE date<2024-10-21

В этом коде SQL при помощи логического сравнения мы получаем задачи, заведённые до определённой даты. Можно попытаться собрать более сложное регулярное выражение, но так мы рискуем выйти за рамки возможностей grep.

В данном случае вам потребуется более сложный инструмент, такой как awk:

awk -F':' '$2<"2024-10-21" {print $1 ":" $2 }' tasks

Awk может справиться одновременно с задачами grep и cut. В данном примере часть

$2<"2024-10-21"

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

Постраничное разбиение результатов при помощи head и tail

В языке SQL предусмотрен оператор LIMIT, при помощи которого можно выбирать конкретное количество элементов из результатов. Вот как выбрать первые две строки:

head -2 tasks

При помощи tail можно получить n последних строк. В совокупности с head мы воспроизводим функционал оператора LIMIT, причём, включая сдвиги. Например, вот как получить строки 2-3:

head -3 tasks | tail -2

Сортировка строк при помощи sort

Во многих SQL-командах важная роль отводится оператору ORDER BY. К счастью, в Linux есть отличная эквивалентная команда sort. Подобно cut и awk, можно указать разделительный знак и поле по номеру, хотя, флагам соответствуют разные буквы. На этот раз t — это разделитель, а k — номер поля:

sort -t':' -k2 tasks

Далее будут отображены все поля, отсортированные по дате:

Объединение таблиц при помощи join

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

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

Затем создадим файл people, в котором будем хранить данные по каждой персоне, чьи задачи мы учитываем:

Теперь можно воспользоваться командой join с разделителем, который указывается через опцию t:

join -t':' -1 5 -2 1 tasks people

При помощи опций -1 и -2 указываем номера тех полей из каждого файла, которые мы собираемся объединять. Здесь речь идёт о первом и пятом полях соответственно. Команда join будет использовать первое поле по умолчанию, так что код можно упростить до:

join -t':' -1 5 tasks people

В результате получим:

Чтобы сделать вывод немного чище, можно конвейеризовать объединённые таблицы. В таком случае получится обрезать и опустить поле name:

join -t':' -1 5 tasks people | cut -d':' -f2-

Кроме того, можно будет объединить два имени в одно при помощи awk:

join -t':' -1 5 tasks people | awk -F':' '{print $2":"$3":"$4":"$5":"$6" "$7}'

Всё вместе

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

SELECT task,date,priority,status,first_name,last_name FROM tasks t LEFT JOIN people p ON t.name=p.name WHERE priority=2 ORDER BY date LIMIT 1

Эквивалентный конвейер команд, пожалуй, несколько сложнее понять, но и в этом нет ничего трудного, если вы знакомы со следующими ключевыми инструментами:

join -t':' -1 5 -2 1 tasks people \   | awk -F':' '{print $2":"$3":"$4":"$5":"$6" "$7}' \   | grep ':2:' \   | sort -t ':' -k2 \   | head -1


ссылка на оригинал статьи https://habr.com/ru/articles/857756/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *