Давайте на примере простого скрипта рассмотрим, как написать скрипт, хранящий данные внутри самого себя. Это будет список задач, хранимый в том же самом скрипте, который добавляет задачи, удаляет их и выводит список задач в его текущем состоянии. Итоговый скрипт будет за вычетом самого списка задач занимать менее 750 байт. Его удобно использовать, например, с Dropbox’ом, Яндекс.Диском или Copy для синхронизации задач между несколькими компьютерами
Самое первое, что нужно сделать - это определить команды, используемые в скрипте и написать обработку параметров командной строки.
case $1 in
add|del|show)
ACTION=$1
shift
TASK=$@
${ACTION}_task
;;
*)
show_help
;;
esac
У нас есть три команды: add, del, show. Самое первое, что сделаем - запомним действие, которое указано в командной строке, в переменную ACTION. Затем сдвинем позиционные параметры скрипта, чтобы удалить из этого списка само действие. Переменной TASK приравняем содержимое командной строки, которое в итоге получится. После этого запустим функцию с именем ДЕЙСТВИЕ_task, которая выполняет соответствующее действие. Если же в качестве первого параметра указано что-то иное или ничего не указано, будет вызвана функция show_help, отображающая краткую помощь. Вот она:
show_help(){
cat << EOF
Description: script which keeps tasks list (or any other list) inside itself
Usage: $0 [add|show|del]'
Commands:
add [task description]
del [task description part (will delete any tasks that include entered string)]
show
EOF
exit
}
Теперь создадим функции, необходимые для выполнения указанных действий. Начнем с простого, с вывода списка задач.
show_task(){
echo "----------TASK LIST--------"
cat << TASKLISTEND
TASKLISTEND
}
Эта функция просто выводит всё, что находится между строкой
cat << TASKLISTEND
и строкой
TASKLISTEND
Именно между этими строками мы и будем хранить список задач. Теперь осталось написать еще две функции: добавление и удаление задачи. Добавлять задачу будем следующим образом:
get_task(){
if [ "$TASK" == "" ]
then
echo -n "Enter task description: "
read TASK
fi
}
add_task(){
get_task
sed -i $0 -re "s/(^TASKLISTEND$)/$TASK\n\1/"
$0 show
}
Непосредственно добавлением задачи занимается функция add_task, а функция get_task просто запрашивает с клавиатуры задачу, если она не была указана в командной строке. Добавление осуществляется потоковым редактором sed. Он выполняет следующее действие: находит в файле $0 (сам файл скрипта) строку, в которой содержится слово “TASKLISTEND” и вставляет перед ним еще одну строку, содержащую описание задачи, и перевод строки.
Удаление реализуется похожим образом:
del_task(){
get_task
sed -i $0 -e "/ TASKLISTEND$/,/^TASKLISTEND$/ {/$TASK/d}"
$0 show
}
Как видите, здесь мы тоже получаем описание задачи при помощи функции get_task, а затем выполняем удаление строки из списка, в которой находится часть описания задачи, попадающей в интервал между двумя строками. Строка начала интервала строк содержит пробел и слово TASKLISTEND в конце строки, а строка конца интервала содержит одно единственное слово TASKLISTEND. Между этими двумя строками мы и удаляем найденную строку, если такая есть.
Вот, собственно, и всё. Полный текст скрипта tsklst.sh:
#!/bin/bash
get_task(){
if [ "$TASK" == "" ]
then
echo -n "Enter task description: "
read TASK
fi
}
add_task(){
get_task
sed -i $0 -re "s/(^TASKLISTEND$)/$TASK\n\1/"
$0 show
}
del_task(){
get_task
sed -i $0 -e "/ TASKLISTEND$/,/^TASKLISTEND$/ {/$TASK/d}"
$0 show
}
show_task(){
echo "----------TASK LIST--------"
cat << TASKLISTEND
TASKLISTEND
}
show_help(){
cat << EOF
Description: script which keeps tasks list (or any other list) inside itself
Usage: $0 [add|show|del]'
Commands:
add [task description]
del [task description part (will delete any tasks that include entered string)]
show
EOF
exit
}
case $1 in
add|del|show)
ACTION=$1
shift
TASK=$@
${ACTION}_task
;;
*)
show_help
;;
esac