Bash
Bash общая информация
Консоль работает с текстом, поэтому центральная задача - обработка текста.
| echo | Просто выводит строку |
| printf |
Выводит строку с модификаторами printf "%s %d" "ff" 22 |
Поиск приложения: whereis name
~ - домашняя директория, ~sergey домашняя директория пользователя sergey
cd без аргументов в домашнюю, cd - в предыдущую
Маски для ls
| ? | один символ |
| * | много символов |
| [set] |
Набор символов, в данном случае s,e,t [a-c] a,b,c [!0-9] где нет цифр |
| {} |
перечисляются наборы текста, например echo f{io,am} |
Утилиты фильтрации текста
| cat |
перенаправление ввода на вывод -b - нумеровать только непустые строки; cat file1 file2 > file3 |
| grep |
поиск строк во вводе Может анализировать один файл или директорию. -e несколько регулярных выражений, например -e ... -e ... -n номер строки, где найдено совпадение -i, --ignore-case - не учитывать регистр символов;
|
| sort |
сортировка строк -b - не учитывать пробелы ls -l | sort -k9 |
| uniq f1 > f2 |
Удаляет повторяющиеся строки |
| cut |
извлечение символов из ввода -b 2-6, 8 отобразит символы от 2 по 6 из строки и 8 -b 5- символы с 5 до конца -с нечто похожее на -b -d ':' -f 1,3 считать разделителем : и оставить первый и третий столбцы |
| sed |
операции изменения данных перед выводом Позволяет вырезать строки, поиск/замена по регулярке, вывод. Крутая штука. |
| tr |
транслирование символов на вводе в другие символы -d набор - удаление символов tr -d '0-9' -s заменяет последовательность повторяющихся символов в SET1 на один такой символ; tr -s ' ' заменит много пробелов на один |
| head | -n кол-во Выводит первые кол-во строк |
| awk |
Считывает построчно данные, выполняет действия и выводит в stdout. Включает целый язык для обработки текста. awk опции 'условие {действие} условие {действие}' Опции: -F, --field-separator - разделитель полей, используется для разбиения текста на колонки; Действия: print(строка) - вывод чего либо в стандартный поток вывода;
Переменные: $NF - последняя строка $(NF-1) - предпоследняя NR - количество строк с начала
awk -F":" '{print $4}' Возьмет строку и по разделителю : выведет 4 элемент Поддерживает регулярные выражения echo -e 'one 1\n two 2' | awk '{sum+=$2} END {print sum}' сумма элементов. awk 'NR < 10' log.txt |
| sed |
Тоже очень крутая штука, этим двум командам посвящена целая книга. |
| diff file1 file2 |
Различие в строках |
| ndiff |
Различие в результатах сканирования nmap
|
| jq |
Утилита для анализа JSON. jq -r '.first' возвращает значение ключа first jq '.[0].plugins.HTTPServer.string[0] определяет следующий элемент:
|
| tail -F filename |
Отображения изменения в файле |
| wget |
Загрузка файлов -q тихий режим -r рекурсивное скачивание -np скачивание файлов из данной директории или ниже -R "index.html" исключить загрузку файлов вида index.html -P foldername директория сохранения |
| curl |
Must have. -s тихий режим -X GET|POST|PUT|DELETE → явный выбор метода -d "param=value" → данные формы (POST)
-H "Header: value" → добавить заголовок
-b "name=value" → передать cookie -o file → сохранить в файл -u user:pass → basic auth -k → игнорировать ошибки сертификатов (небезопасно!) -w "%{http_code}\n" → вывести только HTTP-код |
| find / -name "file.txt" |
Поиск файла |
Редиректы
Вывод в файл:
| Оператор | Значение | Пример |
|---|---|---|
> |
Перенаправить вывод (перезаписать файл) | echo "hi" > file.txt |
>> |
Перенаправить вывод (добавить в файл) | echo "hi" >> file.txt |
Вывод из файла:
| Оператор | Значение | Пример |
|---|---|---|
< |
Чтение из файла | wc -l < file.txt |
<< |
Here document — передаёт блок текста как stdin | cat << EOFстрока1строка2EOF |
<<< |
Here string — передаёт одну строку (или переменную) | grep foo <<< "foo bar baz" |
Фоновые задачи
Фоновые задачи не получают данные от клавиатуры
| Команда | Что делает |
|---|---|
command & |
Запускает процесс в фоне |
jobs |
Показывает список фоновых задач (с job ID: %1, %2 …) |
fg %N |
Переводит задачу номер N в передний план |
bg %N |
Возобновляет приостановленную задачу в фоне |
Ctrl+Z |
Приостанавливает текущий процесс (отправляет в «stopped») |
kill %N |
Завершает задачу по её job ID |
kill PID |
Завершает задачу по PID |
kill -9 PID |
Жёсткое завершение (если обычный kill не помог) |
disown %N |
«Отвязывает» задачу от текущего терминала (будет жить после выхода) |
| `ps aux | grep name` |
pkill -f pattern |
Завершение процессов по шаблону |
Задачи завершаются при закрытии сессии. Через команду nohup можно сделать задачу, работающую после закрытия сессии.
nohup ./myscript.sh &
История ввода команд
Хранится где-то в сессии, сохраняется в .bash_history при закрытии сессии. Для просмотра введенных команд в пределах сессии используется утилита fc
| -l |
Последние 15 команд 4 выведет четвертую команду 4 7 команды с 4 по 7 строка - выведет с первого вхождения строки (из 15) и далее |
| -n | без вывода номеров |
| -e nano |
без дальнейших аргументов - редактирование последней команды и затем исполнение Чтобы не вводить редактор, можно в .bash_profile добавить переменную FCEDIT=nano |
!! исполнение предыдущей команды
Специальные файлы
.bash_profile, .bash_logout, .bashrc Если отсутствуют - используются файл /etc/profile и файлы из /etc/profile.d
.bash_profile - сейчас не используется.
В .profile переменные окружения, .bashrc - скрипты. .bash_login при входе. Но идея осталась.
Последовательность поиска при авторизации, исполняется первый найденный
-
~/.bash_profile -
~/.bash_login -
~/.profile
Исполняет команды при каждом входе в систему.
Итого:
~/.bashrc
Используется в интерактивных (обычных) shell-ах. Сюда кладём то, что нужно только в терминале:
- алиасы (alias ll='ls -lh')
- функции (mkcd() { mkdir -p "$1" && cd "$1"; })
- настройки PS1 (prompt, цвета)
- shopt и настройки истории (HISTSIZE, HISTCONTROL)
- подключение fzf, автодополнений и прочих «тюнингов»
~/.profile
Используется при login-shell (и не только Bash, а sh/dash/zsh тоже могут его читать). Сюда кладём:
- переменные окружения (PATH, EDITOR, LANG, JAVA_HOME)
- настройки, которые должны работать и в GUI-программах (например, экспорт GTK_THEME или XMODIFIERS)
- запуск программ при логине (например, ssh-agent или gnome-keyring-daemon)
~/.bash_profile или ~/.bash_login
Сегодня почти не нужны. Если они есть, то Bash не будет читать ~/.profile.
source .profile - перечитать файл
Alias, options и переменные окружения
Алиасы для команд. Создание алиасов: alias cdvoy='cd sipp/demo/animation/voyager'
Пробел перед закрывающей ' означает ожидание ввода пользователя.
unalias name - удаление
set +o optionname установить опцию, -o убрать. Фиксированный набор. Не впечатлило.
Переменные
Синтаксис: varname='something', использование $varname удаление unset varname
Формат timestamp:
| %a, %A | Аббревиатура дня недели, Полное имя дня недели |
| %b, %B, %m | Аббревиатура имени месяца, Полное имя месяца, Номер месяца в числовом формате |
| %c | Дата и время локали |
| %C |
Последние 2 цифры года |
| %H, %I, %p | Час в 24-часовом формате, Час в 12-часовом формате, эквивалент am/pm |
| %d, %e | Цифра дня, цифра дня с пробелом в случае одной цифры |
| %D | Дата в американском формате (%m/%d/%y) |
| %j | День года 001-366 |
| %M | Минута в десятичном представлении |
| %n, %t | Новая строка, табуляция |
| %R | Время в 24-часовом формате |
| %S | Секунда в десятичном формате |
| %T | Время (час:минута:секунда) |
| %u | Номер дня недели в десятичном формате |
| %U | Номер недели в году |
| %Y | Год |
Строка приглашения
PS1 - основное приглашение
PS2 - при незавершенной строке
В переменной PS1
| Код | Что показывает |
|---|---|
\u |
Имя текущего пользователя |
\h |
Имя хоста (до первой точки) |
\H |
Полное имя хоста |
\w |
Текущая директория (полный путь, с ~ для home) |
\W |
Текущая директория (только имя последней папки) |
\! |
Номер текущей команды в истории |
\# |
Номер команды (считает все команды с момента запуска shell) |
\$ |
Отображает $ для обычного пользователя и # для root |
\t |
Время в формате HH:MM:SS |
\T |
Время в формате HH:MM (12-часовой формат) |
\@ |
Время в формате hh:mm AM/PM |
\d |
Дата (например: Mon Aug 26) |
\n |
Перенос строки |
\s |
Имя используемой оболочки (обычно bash) |
\v |
Версия Bash (например: 5.2) |
\V |
Версия Bash с патч-уровнем |
\j |
Количество фоновых задач, запущенных из shell |
\! |
Номер команды в истории |
\# |
Номер команды (считает все команды в текущей сессии) |
\e или \033 |
Escape-символ (для цветов/ANSI-последовательностей) |
Пример: PS1="\u@\h:\w\$ "
PATH
Просмотр последовательно всех путей.
Добавление в пути: PATH=$PATH":/home/you/bin"
Для ускорения поиска пути к приложениям хранятся в хэш таблице в каждой сессии.
hash -r очищает таблицу хэшей путей.
CDPATH
Аналог path для директорий поиска при использовании cd.
Переменные окружения
Вызванная программа не знает переменных консоли. Для видимости нужно экспортировать переменную в переменную окружения.
| env | Список переменных окружения |
| export varnames | Может быть список через пробел |
| export varname=value command | Доступность переменной только для определенной команды |
source .envfile догружает переменные из файла
Переменные по умолчанию
| BASH_VERSION | Версия |
| BASHPID | |
| GROUPS | Группы текущего пользователя |
| HOSTNAME | Имя хоста |
| OSTYPE | |
| PWD | Текущая рабочая директория |
| RANDOM | Случайное число от 0 до 32767 |
| UID | Идентификатор пользователя |
| SHELL | Полный путь к текущей консоли |
Периферийные функции
| sleep n | Пауза на n секунд |
| seq 1 10 | Последовательность чисел от 1 до 10 |
| date '+%Y-%m-%d %H:%M:%S' | Текущая дата и время |
| tail -f fname | Выводит изменения файла в текущую консоль |
Bash скрипты
При запуске скрипта создается дочерняя консоль, в ней выполняется скрипт и результат возвращается в консоль.
Можно запускать через source, имя (если . в PATH), ./... , и ./ ... & С фоновой задачей аккуратно с объемом вывода, ^C не работает.
Shebang
Лучше использовать shebang в начале (указатель, какую консоль использовать)
#!/bin/bash
| #!/bin/bash -x | Выводит все команды во время исполнения |
| #!/bin/bash -r | Блокирует потенциально опасные действия |
Параметры можно указывать при запуске скрипта, тогда shebang работать не будет.
Удобства
Комментарии #
bash -n script.sh проверка синтаксиса без исполнения скрипта
Внутри можно использовать следующую конструкцию для вывода части скрипта:
#!/bin/bash
...
set -x
...potentially error part...
set +x
Операция ; запускает несколько команд независимо от их статуса завершения
ls; ps; whoami
выполнит все команды
Перенаправления результата выполнения
| > | Stdout в файл, файл очищается |
| >> | Stdout в файл, файл дополняется |
| &> or >& | Stdout и Stderr в файл, файл очищается |
| &>> | Stdout и Stderr в файл, файл дополняется |
| < | Перенаправление ввода в команду |
| << | Перенаправление многострочного ввода в команду |
Номера потоков
0 - stdin, 1 - stdout, 2 - stderr
lzl -l 1> stdout.txt 2>stderr.txt
выведет в stderr.txt
Функции
function functname{
shell commands
}
functname(){
shell commands
}
Используют позиционные переменные.
functname "one" $7
Если внутри функции нужна локальная переменная, то local var1="something", иначе используется глобальная переменная.
Статус возврата из функции перезаписывается после каждого вызова команды, поэтому при необходимости возврата статуса некоторой функции внутри нужно сохранять статус.
cd baddir
echo $?
По умолчанию возвращается статус вызова последней команды. Либо через return N
builtin mkdir "/var/first"
es=$?
echo "$OLDPWD --> $PWD"
return $es
Желательно возвращать код результата, а не просто цифру.
Программы для работы с функциями
| declare | -f список функций с описанием |
| -F только имена функций | |
| unset fname | удалить функцию из памяти |
| type fname | Описание функции |
| -t выведет тип |
Приоритет при вызове из консоли
- Aliases
- Служебные слова типа if, ...
- Функции
- Встроенные команды типа cd, type, ...
- Скрипты и исполняемые команды
Переменные
Строковые (по умолчанию)
Описывается $varname или ${varname} Например есть переменная UID. Для вывода 0_ нужно использовать echo ${varname}_
Удаление переменной unset var1
| $1, $2, ... | Позиционные параметры |
| $* | Строка, содержащая все параметры через пробел |
| $@ | Равна N строкам-параметрам. Актуально при передаче в функции. |
| $# | Количество аргументов |
| var1=$(cmd) | Сохранение результата cmd в переменную |
Определение глобальной переменной: var1="something"
Обработка значений переменных перед вводом
| ${varname:-word } | Если переменная не существует или существует но пустая - вернет word |
| ${varname:=word} | Если переменная не существует или существует но пустая - присвоит ей word и вернет word |
| ${varname:?message} | Если переменная не существует или существует но пустая - выведет сообщение и завершит скрипт |
| ${varname:+word} | Если переменная существует или пустая - вернет word, иначе null |
| ${varname:offset:length} |
Срез. count=frogfootman ${count:4} вернет footman ${count:4:4} вернет foot |
Обработка переменных
|
${var#pattern}
|
Если шаблон совпадает с началом значения переменной - удалить самую короткую часть от начала строки с совпадением и вернуть результат var="/home/user/docs/file.txt" |
| ${var##pattern} |
var="/home/user/docs/file.txt" echo ${var##*/} # file.txt (отрезано всё до последнего "/") |
| ${variable%pattern} |
file="archive.tar.gz" echo ${file%.*} # archive.tar |
| ${variable%%pattern} |
file="archive.tar.gz" echo ${file%%.*} # archive |
| ${variable/pattern/string} |
Наибольшее совпадение шаблона с переменной заменяется строкой. Первое совпадение |
| ${variable//pattern/ string} |
Наибольшее совпадение шаблона с переменной заменяется строкой. Все совпадения |
|
echo -e ${PATH//:/'\n'} выведет разделенное через : значение в значения списком |
Длина значения ${#filename}
Типизированные
При помощи declare <param> var
| -a | Массив |
| -i | Целое число |
| -r | Переменная только для чтения |
| -x | Переменная экспортируется в окружение |
| -f |
Хрень. Возвращает тело функции если она есть.
|
| -F | Возвратит имя функции если она есть. |
Пример:
declare -i val3=12 val4=5
declare -i result2
result2=val3*val
echo $result2
Выведет 60
Использование let
let result="4 * 5"
echo $result
Также можно использовать двойные скобки
let result=$((4 * 5))
echo $result
Есть операции +,-,/,*,%-модуль, += увеличение на константу, -=
Массивы
arr = (1 2 3)
echo "${arr[*]}" #весь массив
echo "${arr[0]}" #1
unset ${arr[1]} #удалит 2 из массива
${arr[0]}=10 #перезапишет 1 в 10
Условия
Условия завершения программы
Условие анализируется не на логическом, а на статусе результата (exit status) выполнения программы. 0 - ОК, 1-255 ошибка.
if condition; then
statements
[elif condition; then
statements...]
[else
statements]
fi
Условие анализа строк
конструкция [], внутри нее возможны условия проверки и сравнения строк.
| str1 = str2 | Строка 1 равна строке 2 |
| str1 != str2 | Строка 1 не равна строке 2 |
| str1 > str2 str1 < str2 | Больше/меньше |
| -n str1 | Строка 1 не пустая |
| -z str1 | Строка 1 пустая |
Условия сравнения чисел
| -lt | Менее чем |
| -le | Меньше или равно |
| -eq | Равно |
| -ge | Больше или равно |
| -gt | Больше |
| -ne | Не равно |
Можно комбинировать
if command && [ condition ]; then
Логика внутри условия
| && или -a |
Выполнить команду 1, если статус 0 - выполнить команду 2
|
| || или -o |
Выполнить команду 1, если статус не 0 - выполнить команду 2
|
| ! |
Отрицание |
Свойства файла, проверяемые в условиях
| -a file, -e file | Файл существует |
| -d file | Директория существует |
| -f file | Файл существует и является файлом (не директория или специальный файл) |
| -r file, -w file | Есть право чтения файла, Есть право записи в файл, |
| -x file | Есть право исполнения файла или право поиска в директории |
| -s file | Файл существует и не пустой |
| -N file | Файл был изменен с момента последнего чтения |
| -O file, -G file | Запустивший скрипт является владельцем файла, Группа запустившего скрипт входит в группу файла |
| file1 -nt file2 | file1 новее file2 (сравниваются время модификации) |
| file1 -ot file2 | file1 старее file2 (сравниваются время модификации) |
Цикл for
Итерируется только по полному списку.
for name [in list]; do
statements that can use $name...
done
Если list не определен, то используется $@
Есть переменная IFS
IFS=:
for dir in $PATH
do
ls -ld $dir
done
break выход из цикла, continue продолжить следующую итерацию
Цикл while
while condition; do
statements...
done
Для бесконечного цикла можно использовать while true; do
Просмотр каждой строки вывода программы (например ping)
#!/bin/bash
ping 172.16.10.1 | while read -r line; do
echo Пинг $line | awk '{print $1 $6}'
done
Цикл until
until command; do
statements...
done
Case
for filename in "$@"; do
pnmfile=${filename%.*}.ppm
case $filename in
*.jpg ) exit 0 ;;
*.tga ) tgatoppm $filename > $pnmfile ;;
*.xpm ) xpmtoppm $filename > $pnmfile ;;
*.pcx ) pcxtoppm $filename > $pnmfile ;;
*.tif ) tifftopnm $filename > $pnmfile ;;
*.gif ) giftopnm $filename > $pnmfile ;;
* ) echo "procfile: $filename is an unknown graphics file."
exit 1 ;;
esac
outfile=${pnmfile%.ppm}.new.jpg
pnmtojpeg $pnmfile > $outfile
rm $pnmfile
done
Опции исполнения
shift смещает переменные влево.
myshift.sh
echo $1 $2
shift
echo $1 $2
Использование: ./myshift.sh one two
Вывод:
one two
two
Вариант скрипта, считывающего параметры со случайным размещением параметров
while [ -n "$(echo $1 | grep '-')" ]; do
case $1 in
-a ) aopt=$2
shift;;
-b ) bopt="True"
;;
-c ) copt=$2
shift;;
* ) echo 'usage: alice [-a] [-b] [-c] args...'
exit 1
esac
shift
done
Опция -b является одинарной, -a и -c параметризованные.
В процессе исполнения можно добавлять интерактивность за счет считывания аргументов
echo "First arg"
read -r farg
echo "First arg is ${farg}"
Вызов другого скрипта
Если есть права на исполнение и правильный shebang то вызов по имени. Скрипт исполняется в подпроцессе.
#!/bin/bash
echo "Это первый скрипт"
./script2.sh # вызов второго скрипта
Если директория script2.sh не в PATH то нужен полный путь.
Для выполнения скрипта в одном процессе, все переменные передаются:
#!/bin/bash
echo "Это первый скрипт"
source script2.sh
Также можно передавать аргументы.
Примеры скриптов
Задача: Есть файл формата кол-во альбомов TAB исполнитель. Нужно вывести первые N исполнителей. Первый аргумент имя файла, второй (необязательный) N. По умолчанию 10.
filename=${1:?'Нужно определить имя файла в первом аргументе!'}
maxcount=${2:-10}
sort -nr $filename | head -n $maxcount
Задача: Обертка для команды ls, которая выводит информацию в человекочитаемом виде.
if [ ! -e "$1" ]; then
echo "Файл $1 не существует"
exit 1
fi
if [ -d "$1" ]; then
echo -n "$1 директория, в которой "
if [ ! -x "$1" ]; then
echo -n "нельзя "
fi
echo "проводить поиск."
elif [ -f "$1" ]; then
echo "$1 обычный файл."
else
echo "$1 специальный файл."
fi
if [ -O "$1" ]; then
echo 'Вы владелец этого файла'
else
echo 'Вы не являетесь владельцем этого файла.'
fi
if [ -r "$1" ]; then
echo 'У вас есть право чтения этого файла.'
fi
if [ -w "$1" ]; then
echo 'У вас есть право записи этого файла.'
fi
if [ -x "$1" -a ! -d "$1" ]; then
echo 'У вас есть право исполнения этого файла.'
fi
Задача: На входе скрипта два параметра: текстовый идентификатор и адрес сайта. Если не хватает параметров - ошибка и выход. Пропинговать адрес, сохранить данные в файл в виде Идентификатор, адрес, результат пинг (Да/Нет), дата и время.
#!/bin/bash
PINGRESULT='ping_result.csv'
ident=${1:?'Нужно определить идентификатор хоста в первом аргументе!'}
myhost=${2:?'Нужно определить адрес хоста во втором аргументе!'}
if [ ! -e "$PINGRESULT" ]; then
touch $PINGRESULT
fi
if [ -d "$PINGRESULT" ]; then
echo "$PINGRESULT это директория. Удалите ее или измените имя файла."
exit 1
fi
declare -i res=$(ping $myhost -c 1 | grep transmitted | awk '{print $4}')
if [ $res -eq "1" ]; then
isaval="Доступен"
else
isaval="Не доступен"
fi
echo ${ident},${myhost},${isaval},$(date '+%Y-%m-%d %H:%M:%S') > $PINGRESULT
Задача: Отправить сообщение пользователю telegram
#!/bin/bash
#sudo apt update && sudo apt install -y jq
#usage ./tgsender "My message"
BOT_TOKEN="..."
# 📢 ID канала или ID user
CHAT_ID="..."
MESSAGE=${1:?"Необходимо определить сообщение в первом аргументе"}
# Запрос в Telegram API
res=$(curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d chat_id="${CHAT_ID}" \
-d text="${MESSAGE}" \
-d parse_mode="Markdown"\
| jq -r '.ok')
if [ "${res}" = "true" ]; then
echo "Ok"
else
echo "Error"
fi
Регулярные выражения
| ^ | начало |
| $ | конец |
| [] |
список символов [1-6] перечисление, может комбинироваться порядок роли не играет [0-5a-fkl] [- если дефис в начале, то как символ ^ Если в начале, то инверсия правила. Если не в начале, то обычный символ |
| | |
или. Желательно экранировать остальное скобками, например gr(e|a)y внутри могут быть полноценные регулярные выражения |
| . | Один любой символ, кроме новой строки \n. |
| ? | 0 или 1 вхождение предшествующего элемента |
| + | 1 и более вхождений предшествующего элемента |
| * | 0 и более вхождений предшествующего элемента |
| \w |
Любая цифра или буква |
| \W | все, кроме буквы или цифры |
| \d | Любая цифра [0-9] |
| \D | все, кроме цифры |
| \xFF | шестнадцатеричное число |
| \s | Любой пробельный символ |
| \S | любой непробельный символ |
| \b | Граница слова |
| \A | начало текста |
| \t, \n, \r | Символ табуляции, новой строки и возврата каретки соответственно |
| {n,m} |
От n до m вхождений {n} ровно n вхождений {n,} от n вхождений {,m} — от 0 до m Иногда нужно экранировать \{ |
| (?i:что-то) | интервальный модификатор, отключающий поиск с учетом регистра для "что-то" |
| (?:что-то) | Атомарная группировка проходит как обычно, но когда процесс поиска выходит за пределы конструкции (за закрывающую круглую скобку), все сохраненные состояния удаляются. |
| (?P<word>...) |
Именованная группа, в данном случае имя - word m.group('word') - пример обращения к группе |
| (?<=...) | Должно совпасть слева (Позитивная ретроспективная проверка), в Python - fixed length. |
| (?<!...) | Не должно совпасть слева (Негативная ретроспективная проверка), в Python не поддерживается. |
| (?=...) | Должно совпасть справа (Позитивная опережающая проверка). |
| (?!...) | Не должно совпасть справа (Негативная опережающая проверка). |
| \g<...> | группы при обратных ссылках, g<1> группа 1 |
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. Чтобы понимал:
echo "123 abc" | grep -P '\d'
| Опция | Описание |
| -P |
Регулярка в стиле Perl |
| -o |
Показать только совпадения |
sed
Правила применяются последовательно, поэтому одно правило может сделать строку, соответствующую второму правилу. И результат замены может быть неожиданным.
| Опция | Описание |
| -e |
Многострочный скрипт в командной строке, sed -e ’s/ MA/ Massachusetts/’ -e ’s/ PA/ Pennsylvania/’ list Но проще через ; sed ’s/ MA/ Massachusetts/; s/ PA/ Pennsylvania/’ list |
Правила для скрипта
| Правило | Описание |
| s |
Замена, файл меняется sed 's/ MA/ Massachusetts/' testone.txt ! случай 's/ MA/, Massachusetts/' не сработал, получилось без запятой. Какой-то нюанс.
|
| -n 's/.../.../p' |
Выводится только соответствующие шаблону, файл не меняется. |
| 's/.../.../g' |
Все вхождения в строке |
| 's/что/на что/число' |
Заменить каждое вхождение с номером Число. 's/foo/bar/2' - второе вхождение foo |
| sed 's/что/на что/w имяфайла' |
сохранить после замены в имяфайла |
| /Sebastopol/s/CA/California/g |
Замена CA на California если есть слово Sebastopol |
| '/.../d' |
Удаление |
awk
Интерпретирует каждую строку как запись и каждое слово как поле. Переменные
$0 полная строка
$1, $2, ... номера полей. Вне awk скрипта $ - параметр bash!
Различные форматы применяются последовательно, например
awk '/VA/ { print $1}' testone.txt
Для строк, в которых есть VA, будет выведено первое поле.
Можно создавать переменные и затем использовать их в сравнении. Переменные создаются внутри {}, используются вне. Изначально все переменные - пустые строки, автоматически инициализируются.
{LastState = $1}
| Параметр | Описание |
| -F |
Разделитель, например awk -F, '{ print $1}' testone.txt |
Правила для скрипта формата {}
| Правило | Описание |
|
Вывод данных awk '{ print $1 }' testone.txt awk '{ print "Name: " $1}' testone.txt |
|
| ; |
Разделитель команд внутри awk '{ print $1; print $2 }' testone.txt |
|
|
Правила для скрипта формата //
| Правило | Описание |
| /some/ |
Поиск с выводом соответствия шаблону awk ’/some/’ list |
Пример совмещения задач
! /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