Каждая из заметок – моя шпаргалка на пару, чтобы не забыть, что по плану нужно рассказать (по сути – тезисы) + расшифровка, чтобы было понятно и неподготовленному читателю. Так что будьте аккуратны – с каждой заметкой вы становитесь чуть ближе к высшему образованию в областях "компьютерные науки" и "компьютерная безопасность".
Повторение
&, |, &&, ||, ;
Выполнение в фоне + задачи:
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 (за это не добавлю и не убавлю).