Программы
Продолжаем дайвить в Bash

Продолжаем дайвить в Bash

awk, sed, примеры программ и разбор их

Оговорюсь заранее:
Каждая из заметок – моя шпаргалка на пару, чтобы не забыть, что по плану нужно рассказать (по сути – тезисы) + расшифровка, чтобы было понятно и неподготовленному читателю. Так что будьте аккуратны – с каждой заметкой вы становитесь чуть ближе к высшему образованию в областях "компьютерные науки" и "компьютерная безопасность".

Повторение

&, |, &&, ||, ;

Выполнение в фоне + задачи:

sleep 12345 &
jobs
fg

Пайпим (переводим вывод одной программы на вход другой):

cat * | less

Ленивые "и" и "или":

[[ 1 eq 1 ]] && echo equals || echo nope

Разделяем команды ";"

while read ln; do echo $ln; done;

cat, head, tail, grep, cut, tr, reverse

Однострочник. Шаг за шагом пишем его и понимаем, что же происходит:

ip addr show \
  | grep "inet" \
  | tr -s " " \
  | cut -d " " -f 3 \
  | cut -d "/" -f 1 \
  | sort -h \
  | reverse

xargs

Представляем вывод одной команды, как параметры другой:

ls -l | xargs file

regexp

Регулярные выражения используются как в утилитах, подобных grep, так и при сравнении в новом test-операторе:

grep '^root:' /etc/passwd

[[ $(pwd) =~ ^$HOME ]] && echo home sweat home

awk

awk читает за один раз одну строку, выполняет определенные действия в зависимости от заданных опций, и выводит результат. Одним из самых простых и популярных способов использования awk является выбор столбца из текстового файла или из вывода другой команды

dpkg -l | awk ' {print $2} ' > installed

Печатает только первый столбец, используя stdin:

cat /etc/hosts | grep ^[^#] | awk '{print $2}'

Печатает все столбцы, используя stdin:

awk '{print $0}'

Пример использования шаблона

cat /etc/hosts | grep ^[^#] | awk '/local/ {print $2}' | uniq

На самом деле, это язык программирования:

#! /bin/awk -f
# This is a program that prints \
"Hello, world!"
# and exits
BEGIN { print "Hello, world!" }

Пример поиска самой большой строки:

awk '{ if (length($0) > max) max = length($0) }
END { print max }'

Имена пользователей (разделитель ставим ":")

awk -F: '{ print $1 }' /etc/passwd | sort

sed

Как и awk — построчное изменение вывода.

cat report.txt | sed 's/Nick/John/g' > report_new.txt

Добавим 8 пробелов в начало:

sed 's/^/        /' file.txt > file_new.txt

Выводит все абзацы, начинающиеся с "Of course" и заканчивающиеся на "attention you pay".

sed -n '/Of course/,/attention you pay/p' myfile

Выводит только строки 12-18 файла file.txt

sed -n 12,18p file.txt

Если найден "boom", заменить aaa на bb:

sed '/boom/s/aaa/bb/' file.txt

Заменяет one на unos независимо от регистра, поэтому будет напечатано "unos TWO"

echo ONE TWO | sed "s/one/unos/I"

grep:

sed '/regexp/!d' file.txt

"Переписывание с доски"

Этот блок появился, потому что на предыдущей паре понял, что ребята не умеют программировать. Ну ничего – маленькими шажками, разбирая простые программы, придём к написанию собственных.

Балуемся с read

#!/bin/bash
echo -n "Введите значение: "
read var
echo "\"var\" = "$var""
echo
echo -n "Введите другое значение: "
read           #  Команда 'read' употребляется без указания переменной для ввода,
               #  тем не менее...
               #  По-умолчанию ввод осуществляется в переменную $REPLY.
var="$REPLY"
echo "\"var\" = "$var""
echo
exit 0

$IFS

echo "Список всех пользователей:"
OIFS=$IFS; IFS=:   # В файле /etc/passwd, в качестве разделителя полей
                   # используется символ ":" .
while read name passwd uid gid fullname ignore
do
    echo "$name ($fullname)"
done < /etc/passwd     # перенаправление ввода.
IFS=$OIFS              # Восстановление предыдущего состояния переменной $IFS.

Команда let производит арифметические операции над переменными. В большинстве случаев, ее можно считать упрощенным вариантом команды expr.

#!/bin/bash
let a=11          # То же, что и 'a=11'
let a=a+5         # Эквивалентно "a = a + 5"
                  # (Двойные кавычки и дополнительные пробелы делают код более удобочитаемым)
echo "11 + 5 = $a"
let "a <<= 3"     # Эквивалентно  let "a = a << 3"
echo "\"\$a\" (=16) после сдвига влево на 3 разряда = $a"
let "a /= 4"      # Эквивалентно let "a = a / 4"
echo "128 / 4 = $a"
let "a -= 5"      # Эквивалентно let "a = a - 5"
echo "32 - 5 = $a"
let "a = a * 10"  # Эквивалентно let "a = a * 10"
echo "27 * 10 = $a"
let "a %= 8"      # Эквивалентно let "a = a % 8"
echo "270 mod 8 = $a  (270 / 8 = 33, остаток = $a)"
exit 0

wc -l

exec < $1
let count=0
while read ln
do
      ((count++))
done
echo $count

Проверка параметра

if [[ $# -lt 1 ]]
then
  echo "Usage: $0 file ..."
  exit 1
fi

Пример работы с функциями

count_lines () {
  local f=$1  
  # this is the return value, i.e. non local
  l=`wc -l $f | sed 's/^\([0-9]*\).*$/\1/'`
}

if [ $# -lt 1 ]
then
  echo "Usage: $0 file ..."
  exit 1
fi

echo "$0 counts the lines of code"
l=0
n=0
s=0
while [ "$*" != ""  ]
do
        count_lines $1
        echo "$1: $l"
        n=$[ $n + 1 ]
        s=$[ $s + $l ]
	shift
done

echo "$n files in total, with $s lines in total"

Уточнение по ДЗ

  • "-" балл за отсутствие usage при "пустом вызове"
  • "-" балл за отсутствие -h и —help
  • "-" балл за ошибки http://www.shellcheck.net/ / "некрасивый" код
  • "+" балл за реализацию того же, но однострочником (отдельный код)

Нельзя пользоваться утилитами group, id и прочими, упрощающими получение данных из /etc/group /etc/passwd. Эти файлы – первоисточники информации, их и используйте!

Наш cut будет вырезать со строки $1 по стороку $2. Не забывайте, что может быть $2 < $1. + Рассказать, что делает оригинальный cut (за это не добавлю и не убавлю).

Также может быть вам интересно:

Немного о написании патентов

На днях зарегистрировали патент за моим авторством. Писать патенты — довольно забавное занятие — сильно отличается от какого-либо из реального мира.

Читать »

Top500, отчёт о DDoS, Mozilla получит $1 млрд

IT-Дайджест за эту неделю: рейтинг суперкомпьютеров, 50-кубитный квантовый компьютер, Firefox 57.0 «Quantum», Fedora 27

Читать »
Фото Как сделать свою middleware в Django (с примерами)

Как сделать свою middleware в Django (с примерами)

Middleware или "промежуточное программное обеспечение" - элегантный способ установить общие правила обработки запросов и ответов приложения. Давайте напишем парочку middleware, чтобы понять, как они работают.

Фото Как настроить отправку почты из Django

Как настроить отправку почты из Django

Письма об ошибках, отчёты на почту, восстановление паролей - всё это полезно при работе с сайтом. Django предоставляет удобный способ это сделать с минимумом настроек!

Фото Добавляем поддержку медиа-файлов в Django проект

Добавляем поддержку медиа-файлов в Django проект

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

Фото Настройка журналирования (логирования) в Python с примерами

Настройка журналирования (логирования) в Python с примерами

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

Фото Новый оператор match-case в Python

Новый оператор match-case в Python

В новой версии Python (3.10) появится новый оператор. Новый оператор сопоставления по шаблону (match-case).

Фото Нет слов, одни... однострочники

Нет слов, одни... однострочники

На днях вышел пост со списком полезных однострочников для JavaScript программистов. Памятуя Perl-овую молодость, заглянул туда.

Фото Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

В Django вы можете передавать данные в шаблоны посредством контекстов. Контекст передаётся из контроллера (view в терминах Django), однако, если одни и те же данные нужны в разных местах, лучше сделать свой контекст-процессор.

Фото Пример своей консольной команды в Django проекте

Пример своей консольной команды в Django проекте

Если вы работали с Django проектом, то, скорее всего, запускали команды из консоли (manage.py). В Django есть простой способ писать свои команды для управления проектом.