# Grep, awk, sed

Общий синтаксис для sed и awk: command \[options\] script filename

Если скрипт определяется в команде, то одинарные кавычки.

-f filename имя скрипта

Каждая инструкция скрипта состоит из блока шаблона и процедуры. Шаблон отделяется /. Строки скрипта интерпретируются последовательно, если найдено соответствие шаблону - исполняется процедура. Применяется каждая строка скрипта. Sed выводит строку, поведение awk нужно определять в скрипте. В скриптовом файле шаблон пишется без кавычек

```
cat sedscr
s/ MA/, Massachusetts/
s/ PA/, Pennsylvania/
s/ CA/, California/
s/ VA/, Virginia/
s/ OK/, Oklahoma/
```

**grep**

Регулярки пишутся в двойных кавычках

grep "\[PV\]A" testone.txt

grep "10\\{1,2\\}1" testone.txt

grep по умолчанию не понимает спецсимволы типа \\d,... \\d интерпретируется как символ d. Чтобы понимал:

```bash
echo "123 abc" | grep -P '\d'
```

<table border="1" id="bkmrk-%D0%9E%D0%BF%D1%86%D0%B8%D1%8F-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5--e-%D0%9C%D0%BD" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22.7977%;"></col><col style="width: 77.3215%;"></col></colgroup><thead><tr><td class="align-center">Опция</td><td class="align-center">Описание</td></tr></thead><tbody><tr><td>-P</td><td>Регулярка в стиле Perl

</td></tr><tr><td>-o</td><td>Показать только совпадения

</td></tr></tbody></table>

**sed**

Правила применяются последовательно, поэтому одно правило может сделать строку, соответствующую второму правилу. И результат замены может быть неожиданным.

<table border="1" id="bkmrk-%D0%9E%D0%BF%D1%86%D0%B8%D1%8F-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5--e-%D0%9C%D0%BD-1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22.7977%;"></col><col style="width: 77.3215%;"></col></colgroup><thead><tr><td class="align-center">Опция</td><td class="align-center">Описание</td></tr></thead><tbody><tr><td>-e</td><td>Многострочный скрипт в командной строке,

sed -e ’s/ MA/ Massachusetts/’ -e ’s/ PA/ Pennsylvania/’ list

Но проще через ;

sed ’s/ MA/ Massachusetts/; s/ PA/ Pennsylvania/’ list

</td></tr></tbody></table>

Правила для скрипта

<table border="1" id="bkmrk-%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%BE-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-s-%D0%97" style="border-collapse: collapse; width: 100%; height: 275.766px;"><colgroup><col style="width: 33.4826%;"></col><col style="width: 66.5174%;"></col></colgroup><thead><tr style="height: 29.7969px;"><td class="align-center" style="height: 29.7969px;">Правило</td><td class="align-center" style="height: 29.7969px;">Описание</td></tr></thead><tbody><tr style="height: 80.1875px;"><td style="height: 80.1875px;">s</td><td style="height: 80.1875px;">Замена, файл меняется

sed 's/ MA/ Massachusetts/' testone.txt

<span style="color: rgb(224, 62, 45);">! случай 's/ MA/, Massachusetts/' не сработал, получилось без запятой. Какой-то нюанс.</span>

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">-n 's/.../.../p'</td><td style="height: 29.7969px;">Выводится только соответствующие шаблону, файл не меняется.

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">'s/.../.../g'</td><td style="height: 29.7969px;">Все вхождения в строке

</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">'s/что/на что/число'</td><td style="height: 46.5938px;">Заменить каждое вхождение с номером Число.

's/foo/bar/2' - второе вхождение foo

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">sed 's/что/на что/w имяфайла'</td><td style="height: 29.7969px;">сохранить после замены в имяфайла

</td></tr><tr><td>/Sebastopol/s/CA/California/g</td><td>Замена CA на California если есть слово Sebastopol

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">'/.../d'</td><td style="height: 29.7969px;">Удаление

</td></tr></tbody></table>

**awk**

Интерпретирует каждую строку как запись и каждое слово как поле. Переменные

$0 полная строка

$1, $2, ... номера полей. <span style="color: rgb(224, 62, 45);">Вне awk скрипта $ - параметр bash!</span>

Различные форматы применяются последовательно, например

```bash
awk '/VA/ { print $1}' testone.txt
```

Для строк, в которых есть VA, будет выведено первое поле.

Можно создавать переменные и затем использовать их в сравнении. Переменные создаются внутри {}, используются вне. Изначально все переменные - пустые строки, автоматически инициализируются.

```bash
{LastState = $1}
```

<table border="1" id="bkmrk-%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5--f" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22.7977%;"></col><col style="width: 77.3215%;"></col></colgroup><thead><tr><td class="align-center">Параметр</td><td class="align-center">Описание</td></tr></thead><tbody><tr><td>-F</td><td>Разделитель, например

awk -F, '{ print $1}' testone.txt

</td></tr><tr><td> </td><td> </td></tr></tbody></table>

Правила для скрипта формата {}

<table border="1" id="bkmrk-%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%BE-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-pri" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22.7977%;"></col><col style="width: 77.3215%;"></col></colgroup><thead><tr><td class="align-center">Правило</td><td class="align-center">Описание</td></tr></thead><tbody><tr><td>print</td><td>Вывод данных

awk '{ print $1 }' testone.txt

awk '{ print "Name: " $1}' testone.txt

</td></tr><tr><td>;</td><td>Разделитель команд внутри

awk '{ print $1; print $2 }' testone.txt

</td></tr><tr><td>  
</td><td></td></tr></tbody></table>

Правила для скрипта формата //

<table border="1" id="bkmrk-%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%BE-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%2Fso" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22.7977%;"></col><col style="width: 77.3215%;"></col></colgroup><thead><tr><td class="align-center">Правило</td><td class="align-center">Описание</td></tr></thead><tbody><tr><td>/some/</td><td>Поиск с выводом соответствия шаблону

awk ’/some/’ list

</td></tr><tr><td> </td><td> </td></tr></tbody></table>

Пример совмещения задач

```bash
! /bin/sh
awk -F, '{print $4 ", " $0}' $* |
sort |
awk -F, '
$1 == LastState {print "\t" $2}
$1 != LastState {LastState = $1; print $1; print "\t" $2}
'
```

Вывод

```
 CA
         Amy Wilde
 Massachusetts
         Eric Adams
         John Daggett
         Sal Carpenter
 OK
         Orville Thomas
 PA
         Terry Kalkas
 VA
         Alice Ford
         Hubert Sims
```