mirror of
https://github.com/eddyem/lectures.git
synced 2025-12-06 02:35:18 +03:00
384 lines
12 KiB
TeX
384 lines
12 KiB
TeX
\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} |