---
# System prepended metadata

title: Лабораторная работа №4 "Bash-однострочник" (Остапенко В.Ю.)

---

# Лабораторная работа №4 "Bash-однострочник" (Остапенко В.Ю.)

---

## **Цели работы:**
- Самостоятельно изучить основы программирования на bash.
- Приобретение навыка обработки текстовой информации bash-скриптом.

---

## Ход работы

### Задание: Написать однострочный скрипт на bash, в котором сравниваются 2 файла: sitelist1 и sitelist2. 

:::info
Результатом этого однострочника должно быть удаление строк, которые содержатся в sitelist1, из sitelist2. Иначе говоря, из sitelist2 должны быть удалены задублированные относительно sitelist1 строки.
:::

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

При попытки загуглить команду для удаления строки из файла была найдена команда **sed**, на самом деле она способна на гораздо большее, чем просто удалять строки, но в данном случае мне это не понадобиться. В общем виде, комнада будет выглядить примерно так:

```bash
$ sed -i -e '/[регулярное выражение]/d' файл.txt
```

:::info
Где параметр **d** указывает на удаление строки; **-i** - сохраняет файл (без него изменения выводятся в терминал); **-e** - не обязательный параметр, указывающий, что далее идёт скрипт (в нешем случае Регулярное выражение)
:::

Теперь, надо каким-то образом подставить строки из второго файла в качестве паттерна в регулярное выражение.

Для этого воспользуюси циклом **for**, который будет по очереди доставать строки из второго файла, и подставлять их в регулярку.

Однострочный **for** отличается от обычного лишь **;** перед **do** и **done**. 
В качестве объекта итерации используем второй файл, но чтобы сообщить это циклу использую следующий способ:



```bash
for var in $(cat sitelist2.txt); do; done;
```

:::info
Использование $ как $(комманда) означает запуск всего, что находится внутри круглых скобок, в подоболочке и возврат его в качестве значения для внешней команды. Т.е. цикл будет проходить по строкам из второго файла.
:::

Теперь собираю готовую команду:

```bash
for var in $(cat sitelist2.txt); do sed -i -e "/^$var/d" sitelist1.txt; done
```

:::info
В регулярном выражении присутствует символ "**^**", он указывает на то, что проверка идёт с начала строки.
:::

Для нагядности результата проверим два момента:

1) Количество строк в первом файле, до и после скрипта

2) Конкретное значение (например "tele2.ru")

Начнём.

ДО:

1) 321 строка
![](https://i.imgur.com/7GkQ6bo.png)

2) Строка "tele2.ru" присутсвует в обоих файлах
![](https://i.imgur.com/mePxZPT.png)

Выполнение скрипта:

![](https://i.imgur.com/THyVBSm.png)

ПОСЛЕ:

1) 310 Строк
![](https://i.imgur.com/4C7d2Mw.png)

2) Строка **tele2.ru** отсутвует (осталась строка лишь содержащая данную строку - t2wd.tele2.ru) 
![](https://i.imgur.com/3P210uk.png)
 
 
:::success
УСПЕХ!
:::


---



### Заключение

#### В ходе выполнения был получен опыт написания bash скриптов, использвания команды **sed**, изучены циклы и условия (в данной работе был использован цикл **for**), и др.