lectures/Komp_obr_SFedU/01_Pract.tex
2021-11-11 20:44:40 +03:00

384 lines
12 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\documentclass[10pt,pdf,hyperref={unicode}]{beamer}
\hypersetup{pdfpagemode=FullScreen}
\usepackage{lect}
\usepackage{listings}
\lstloadlanguages{Octave,C,bash}
\lstset{language=bash}
\title[Компьютерная обработка. Практикум 1.]{Компьютерная обработка результатов измерений}
\subtitle{Практикум 1. Работа с файлами в bash.}
\date{}
\begin{document}
% Титул
\begin{frame}{}
\maketitle
\end{frame}
\begin{frame}{Linux}
\begin{block}{}
Ядро. GNU is not UNIX. <<Бритва Оккама>>: UNIX-way и KISS. <<Трубы>>.
Файловые системы: транзакции, права доступа и аттрибуты файлов, <<все есть файл>>~--- псевдофайлы.
Монтирование ФС. Команды \t{mount}, \t{df}, \t{du}. Ссылки на файлы: \t{ln}.
Структура файловой системы: базовые директории.
Терминалы и псевдотерминалы. Командные оболочки. Команды \t{man} и \t{apropos}. Приглашение
командной строки: \t{\$PS1}.
Рабочая директория: \t{pwd} и \t{\$PWD}. Команда \t{env}. Команда \t{alias}.
\end{block}
\end{frame}
\begin{frame}{Базовые файловые операции}
\only<1>{
\begin{block}{}
\t{ls}~-- отображение содержимого каталога.
\t{cd}~-- переход в другой каталог.
\t{mkdir}~-- создать каталог, \t{rmdir}~-- удалить.
\t{rm}~-- удалить файлы, каталоги.
\t{find}~-- поиск файла; \t{locate}~-- быстрый поиск с использованием базы данных.
\t{touch}~-- создать файл либо изменить атрибуты существующего.
\t{echo}~-- вывод в терминал данных.
\t{reset}~-- сброс настроек терминала.
\end{block}
}\only<2>{
\begin{block}{Специальные устройства}
\t{/dev/zero} при чтении возвращает нули.\\
\t{/dev/null} уничтожает все данные, которые в него пишут.\\
\t{/dev/random} случайные числа (требует <<энтропии>>).\\
\t{/dev/urandom} псевдослучайные числа.
\end{block}
}
\end{frame}
\begin{frame}{Переменные, скобки, возвращаемое значение}
\begin{block}{}
\t{x="text"; echo "\$x"; echo "\$\{x\}"}. \t{echo "{}'\$x'=\$x"}.
\t{echo "\bsl\$x=\$x"}. \t{unset x}. \t{set}. \t{env}.
\t{echo `ls`} и \t{echo \$(ls)}. \t{let a=25+3}.
\t{\$\{VAR-default\}}, \t{\$\{VAR=default\}}~-- значение по умолчанию.
\t{\$\{VAR?err message\}}~-- выдача сообщения.
\t{\$\{VAR:pos[:len]\}}~-- подстрока с \t{pos} длины \t{len}.
Математика: \t{var1=\$((5 + 5))}, \t{var2=\$((\$var1 * 2))}.
Возвращаемое значение: \t{\$?}. Если возвращается не 0, то это обычно~--- код ошибки.
Например: \t{команда1 \&\& команда2 || команда3}.\\
Команды можно объединять: \t{оманда1; команда2; команда3)} (скобка вернет код возврата
последней команды).
\end{block}
\end{frame}
\begin{frame}[fragile]{Скрипты}
\begin{block}{Шебанг}
\t{\#!/bin/bash} или \t{\#!/bin/sh}. Шебанг необязателен, если скрипт можно вызывать в том
же сеансе bash (однако, в случае проблемы сеанс может <<упасть>>).
\end{block}
\begin{block}{Аргументы}
\t{\$N}~-- N-й аргумент (\t{\$0}~-- имя скрипта). \t{\$\#}~-- количество аргументов.
\t{\$*} и \t{\$@}:
\begin{lstlisting}
function chkargs(){
echo "you give $# arguments:"
for arg in "$@"; do
echo -e "\t$arg"
done
}
chkargs "$@"
chkargs "$*"
chkargs $*
\end{lstlisting}
\end{block}
\end{frame}
\begin{frame}{Вывод\slash вывод файлов, перенаправление вывода}
\only<1>{
\begin{block}{Команда \t{man}}
Выводит справку по флагам различных утилит. \t{man man}.
\end{block}
\begin{block}{}
Вывод содержимого файла: \t{cat file}. Перенаправление в другой файл: \t{cat file1 >
file2}.
Номера стандартных дескрипторов: 0~-- stdin, 1~-- stdout, 2~-- stderr:
\t{cat \$file 2>/dev/null}.
\t{tail -n N}~-- отображение $N$ строк с конца файла. Чаще с флагом \t{-f} (для
непрерывного
перечитывания файла в процессе добавления новых строк).
\t{head -n N}~-- отображение $N$ строк с начала файла. Часто~--- в комбинации с \t{tail}.
Команды \t{less} и \t{more} позволяют интерактивно перемещаться по тексту (доступен также
поиск, переход на $N$-ю строку и т.д.).
\end{block}
}\only<2>{
\begin{block}{}
Каналы помогают перенаправить вывод одной команды на ввод другой. Например: \t{ls -l |
less}.\\
\t{read}~-- считать данные со стандартного ввода\\
\t{>>} позволяет дописывать файл. Например:\\
\t{> filelist; while read x; do ls \$x >> filelist; done}\\
\t{exec 1 > myfile}~-- перенаправить stdout в файл\\
\t{exec 2 > errfile}~-- перенаправить stderr\\
\t{exec 2 > \&1}~-- перенаправить stderr в stdout\\
\t{exec 0 < file}~-- читать данные не с stdin, а из файла\\
Временное: \t{exec 4 < \&0; exec 0 < myfile; \ldots ; exec 0 < \&4}
\end{block}
}
\end{frame}
\begin{frame}[fragile]{Условия}
\begin{block}{}
\t{if [ условие ]; then true; else false; fi}
\t{[ условие ] \&\& true || false}.
\end{block}
\begin{lstlisting}
echo "Enter value"
read val
if [ $val -gt 100 ]; then
echo "value $val greater than 100";
else
echo "value $val less than 100";
fi
\end{lstlisting}
\begin{lstlisting}
echo "Enter filename"
read f
[ -d $f ] && echo "$f is a directory"
[ -f $f ] && echo "$f is a file"
[ ! -e $f ] && echo "Not exists"
\end{lstlisting}
\end{frame}
\begin{frame}[fragile]{\t{case}}
\begin{lstlisting}
while [ -n "$1" ];do
case "$1" in
-a) echo "Found the -a option" ;;
-b) echo "Found the -b option" ;;
-c) echo "Found the -c option" ;;
*) echo "$1 is not an option" ;;
esac
shift
done
\end{lstlisting}
\end{frame}
\begin{frame}[fragile]{Цикл \t{for}}
\begin{lstlisting}
echo -e "\t1."
for (( a = 1; a < 11; ++a )); do
echo "a=$a"
done
echo -e "\n\t2."
for a in $(seq 1 10); do
echo "a=$a"
done
echo -e "\n\t3."
for a in one "two args" three; do
echo "a=$a"
done
\end{lstlisting}
\end{frame}
\begin{frame}[fragile]{Цикл \t{while}}
\begin{lstlisting}
#!/bin/bash
while read X; do
echo "You entered: $X"
done
echo "End"
\end{lstlisting}
\begin{lstlisting}
./w
Hello
You entered: Hello
More words
You entered: More words
^D
End
\end{lstlisting}
\end{frame}
\begin{frame}[fragile]{Массивы}
\small
\begin{lstlisting}
array=(1 2 3 4 [5]=next [10]=last)
echo -n "array with size ${#array[*]} and indexes"
echo " ${!array[*]}: ${array[*]}"
echo "array[4]=${array[4]}, array[10] len=${#array[10]}"
\end{lstlisting}
Результат:
\begin{lstlisting}
array with size 6 and indexes 0 1 2 3 5 10: 1 2 3 4 next last
array[4]=, array[10] len=4
\end{lstlisting}
+ скрипт \t{takeexp}.
\end{frame}
\begin{frame}{Поиск и редактирование в файлах}
\only<1>{
\begin{block}{\t{grep}}
\t{grep take takeexp}\\
\t{echo -e "first line\bsl nsecond line\bsl nafirst line" \vl grep first}\\
\t{echo -e "first line\bsl nsecond line\bsl nafirst line" \vl grep -w first}\\
Отобразить N линий до, после или вокруг: \t{-BN}, \t{-AN}, \t{-CN}.\\
Рекурсивный поиск: \t{-R}.\\
Инверсия поиска: \t{-v}.\\
Вывод номера строки: \t{-n}, имени файла: \t{-H}.\\
Поиск нескольких фраз: \t{-e фраза}.\\
Регулярные выражения: \t{grep [0-9] file};\\
IP-адрес: \t{grep -E "[0-9]\{,3\}\bsl.[0-9]\{,3\}\bsl.[0-9]\{,3\}\bsl.[0-9]\{,3\}".\\
Конструкция \t{\{min,max\}}.
}
\end{block}
}\only<2>{
\begin{block}{\t{sed}}
\t{sed 's/test/another test/g' ./myfile}\\
\t{sed -e 's/This/That/' -e 's/test/another test/' ./myfile}\\
Применение результатов к самому файлу: \t{-i}\\
Удаление строк: \t{sed '2,3d' myfile} и по шаблону: \t{sed '/test/d' file}\\
Удаление диапазона по шаблону: \t{sed '/first/,/last/d' file}\\
Добавить строку до заданной: \t{sed '5i newline' file}\\
Добавить после заданной: \t{sed '5a newline' file}\\
Заменить строку: \t{sed '2c newline' file}\\
Замена отдельных символов: \t{sed 'y/oldset/newset'}\\
Вставка файла: \t{sed '4r file2' file1}\\
\end{block}
}\only<3>{
\begin{block}{\t{awk}}
Вывод полей с номерами: \t{awk -F: '\{print \$1 \$4\}' file} (\t{-F}~-- разделитель)\\
\t{echo "My name is Tom" | awk '\{\$4="Adam"; print \$0\}'}\\
Выполнение команд в начале: \t{awk 'BEGIN \{print "Hello World!"\}'}\\
Команды в конце: \t{awk 'END \{print "End of File"\}'}\\
Использование скриптов в файле: \t{awk -f awkscript1 /etc/passwd}\\
Условный оператор: \t{awk '\{if (\$1 > 20) print \$1\}' file}\\
\t{echo -e "10\bsl n20\bsl n30\bsl n40\bsl n50" | awk -f awkscript2}\\
Математика: \t{awk 'BEGIN\{x=exp(5); print x\}'}
\end{block}
}
\end{frame}
\begin{frame}[fragile]{Регулярные выражения}
Спецсимволы: \verb'.*[]^${}\+?|()' (нуждаются в экранировании).\\
\verb'^'~-- начало строки, \verb'$'~-- конце строки.\\
Спецклассы: \verb'[[:alpha:]]', \verb'[[:alnum:]]', \verb'[[:blank:]]', \verb'[[:digit:]]',
\verb'[[:upper:]]', \verb'[[:lower:]]', \verb'[[:print:]]', \verb'[[:punct:]]',
\verb'[[:space:]]'.\\
Символ <<или>>: \t{\vl}. \verb'echo -e "one\ntwo\nthree" | grep -P "one|three"'.\\
Количество включений: \verb'{{min,max}}'.\\
Группировка в скобках: \verb'echo -e "testtest\na test\ntesttesttest" | grep -P "(test){3}"'.\\
\t{grep -G} (базовые регулярные) и \t{grep -P} (расширенные регулярные).
Проверка адреса электронной почты:
\verb'^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$'
\end{frame}
\begin{frame}[fragile]{}
\begin{block}{Нестандартные баш-скрипты}
\lstset{language=C}
\begin{lstlisting}
//usr/bin/gcc $0 && exec ./a.out "$@"
#include <stdio.h>
int main(int argc, char **argv){
for(int x = 1; x < argc; ++x)
printf("arg %d is %s\n", x, argv[x]);
printf("Done\n");
return 0;
}
\end{lstlisting}
\lstset{language=bash}
Запуск:
\begin{lstlisting}
./a.c some "amount of" data
arg 1 is some
arg 2 is amount of
arg 3 is data
Done
\end{lstlisting}
\end{block}
\end{frame}
\begin{frame}{Примеры}
\begin{block}{}
\begin{enumerate}
\item Получить псевдослучайное число длиной $N$ символов из \t{/dev/urandom}.
\item Заполнить таблицу в 100~строк с шаблоном: столбец~1~--- номер строки, столбец~2~---
псевдослучайное число от~0 до~1000, столбец~3~--- псевдослучайное число от~-20 до~20, столбец~4~---
псевдослучайное число с фиксированной точкой от~0 до~100 с~3 знаками после запятой.
\item Отсортировать таблицу из предыдущего примера по 2, 3 и 4 столбцу.
\item В цикле сгенерировать из \t{/dev/urandom} последовательности латинских букв длиной до 100.
Если в последовательности есть искомая (введенная с клавиатуры), отобразить ее на экране.
Продолжать до нахождения 5 вхождений или же до достижения 10000 проверок. Вывести на экран
количество <<попаданий>> и <<промахов>>, а также процентную долю <<попаданий>> по отношению ко всем
испытаниям.
\end{enumerate}
\end{block}
\end{frame}
\begin{frame}{Задания}
\begin{block}{}
\only<1>{
\begin{enumerate}
\item Прочитайте \t{man column}. При помощи этой утилиты отформатируйте в читабельном виде вывод
скрипта скрипта из третьего примера. Попробуйте несколько разных видов оформления.
\item Модифицируйте скрипт \t{takeexp} так, чтобы он брал данные из файла, в котором они хранятся в
табличном виде (построчно): номер позиции, время экспозиции в миллисекундах, фокусное расстояние в
условных отсчетах.
\item Напишите скрипт, проверяющий, являются ли данные в таблице членами <<магического квадрата>>
$4\times 4$ (сумма по строкам, столбцам и диагоналям должна быть одинаковой).
\item Сгенерируйте 999 случайных целых чисел от~0 до~1000. При помощи \t{sort}, \t{head} и \t{tail}
найдите медиану полученного ряда.
\savei
\end{enumerate}
}\only<2>{
\begin{enumerate}
\conti
\item Сгенерируйте 10000 случайных целых чисел от~0 до~99. Создайте файл, в который занесите
гистограмму распределения чисел (первая колонка~--- числа, вторая~--- количество их в ряду данных).
Отформатируйте таблицу при помощи утилиты \t{column}.
\item Нарисуйте в \t{bash} горизонтальную гистограмму по данным из предыдущего задания (значение
фиксированной длины, за которым следует поле из символов \t{*} в нужном количестве). Используйте
форматированный вывод (например, \t{printf "\%-4d\%.5s\bsl n"\, 123
"*******************************"}.
Попробуйте другой способ нарисовать такую гистограмму.
Учтите, что ширина вывода должна должна быть ограничена заданным числом (80 или 100 символов).
\item Используя циклы и массивы, нарисуйте вертикальную гистограмму. Учтите, что рисовать придется
сверху-вниз.
\item Почитайте об escape-символах. Попробуйте вывести горизонтальную гистограмму в четырех
градациях цвета ($0\div25\%$ максимума~--- одним цветом, $25\div50\%$~--- другим и т.д.).
\end{enumerate}
}
\end{block}
\end{frame}
\end{document}