Z: DBFILE
Добавление в БД
Функции Функции
Функция для проверки длины строки:
length_check()
{
# length_check
# $1=строка, $2=длина строки не превышает этого значения
_STR=$1
_МАХ=$2
_LENGTH=`echo $_STR | awk '{print length ($0) }"`
if [ "$_LENGTH" -gt "$_MAX" ]; then
return 1
else
return 0
fi
}
Функция, выполняющая проверку наличия в строке исключительно числовых данных:
a_number ()
#вызов: a_number $1=string
{
_NUM=$1
_NUM=`echo $1 awk '{if($0~/[^0-9]/) print "1")'`
if [ "$_NUM" != "" ]
then
#ошибки
return 1
else
return 0
fi
}
Функция, позволяющая определить, состоит ли строка исключительно из одних символов:
( [^0-9a-zA-Zа-яёА-ЯЁ] ---> общее регулярное выражение)
characters()
#characters
#$1=string , вызов: char_name string
{
_LETTERS_ONLY=$1
_LETTERS_ONLY=`echo $1|awk '{if($0~/[^a-zA-Z]/) print "l"}'`
if [ "$_LETTERS_ONLY" != "" ]
then
return 1
else
return 0
fi
}
При просмотре полей можно просто вызвать необходимую функцию и затем проверить коды возврата. Чтобы сообщения находились на экране до тех пор, пока пользователь не нажмет на клавишу для их удаления, нужно воспользоваться командным приглашением.
Функция реализующая командное приглашение read_a_char.
continue_promptYN()
{
# continue_prompt
echo -n "Hit any key to continue.."
DUMMY=`read_a_char`
}
Когда вводятся данные пользователя, содержащие номер служащего, нужно убедиться, что ранее подобная информация не вводилась, т.е поле должно быть уникальным. Одним из способов для выполнения этой задачи является применение команды grep. С помощью команды grep выполняется поиск номера служащего, который содержится в строке _CODE. Если утилита awk не возвращает какого-либо значения, то дублирующиеся значения отсутствуют и функция завершает выполнение с кодом возврата Ø. Ниже приводится код этой функции.
(Обратите внимание, что для нахождения точного соответствия в команде grep используется выражение "$_CODE\>". Двойные кавычки служат для сохранения значения переменной; при использовании одинарных кавычек ничего возвращаться не будет.)
check_duplicate()
{
#check_duplicate
#проверка дубликата номера служащего
_CODE=$1
MATCH=`grep "$_CODE\>" $DBFILE`
echo $_CODE
if [ "$MATCH" = "" ]; then
return 0 # нет дублирования
else
return 1 # дубликат найден
fi
}
Код, выполняющий проверку номера служащего.
Вся информация обрабатывается в цикле while (фактически, каждое поле, содержащее записи данных, обрабатывается в отдельном цикле while). Поэтому, если имеется недействительная запись, последует запрос о просмотре ее исходного значения.
while : do
echo -n "Employee Staff Number :"
read NUM
# проверка вводимых данных
if [ "$NUM" != "" ]; then
if a_number $NUM; then
# номер OK
NUM_PASS=0
else
NUM_PASS=1
fi
if length_check $NUM 10; then
# длина OK
LEN_PASS=0
else
LEN_PASS=1
fi
#====================================
# проверка наличия дубликатов…
if check_duplicate $NUM; then
# нет дубликатов
DUPLICATED=0
else
DUPLICATED=1
echo "Staff Number: There ls already an employee with this number"
continue_prompt
fi
#====================================
# проверка значений всех трех переменных; все они должны выполняться
if [ "$LEN_PASS" = "0" -a "$NUM_PASS" = "0" -a "$DUPLICATE" = "0" ]
then
break
else
echo "Staff Number: Non Numeric or Too Many Numbers In Field"
continue_prompt
fi
else
echo "Staff Number: No Input Detected, This Field Requires a Number"
continue_prompt
fi
done
После просмотра номера служащего проверяется, содержатся ли в поле данные:
if [ "$NUM" != "" ]
Если поле не содержит данные для ввода, не выполняется часть then конструкции if. В части else, которая завершает код подтверждения поля, отображается следующее сообщение:
Staff Number: No Input Detected, This Field Requires a Number
Часть then производит все необходимые проверки правильности вводимых данных. При условии, что имеются вводные данные, вызывается функция a_number. Эта функция проверяет, содержит ли передаваемая строка числовые данные; если это так, функция возвращает значение Ø, в противном случае возвращается значение 1, На базе возвращаемых значений флагу num_pass присваивается либо значение Ø (успешный возврат - наличие строки из чисел), либо значение 1 (неудачный возврат - cтрока не является числовой).
Затем вызывается функция length check. Эта функция передает не только строку, но и максимальное число символов, содержащихся в строке. В данном случае передается десять символов. Если количество символов меньшеили равно максимальной величине, отображается значение Ø; иначе возвращается значение 1. Флаг len_PASS принимает либо значение Ø (в случае успешного возврата, когда длина строки не превышает максимального значения), либо значение 1 (при неудачном возврате, если получена строка, длина которой равна максимальному значению).
Проверка наличия дубликатов для номеров служащих, выполняет функция check_duplicate. Если дубликаты не обнаружены, флагу DUPLICATE присваивается значение 1. Теперь нужно убедиться, что все три флага имеют значение Ø (ошибки отсутствуют). Для этого воспользуемся логической функцией and. При выполнении части then обе части уравнения должны принять истинное значение.
Если проверка завершилась успешно, значение поля подтверждается. Поскольку цикл while выполняется непрерывно, следует с помощью команды break прервать его выполнение.
if [ "$LEN_PASS" = "0" -a "$NUM_PASS" = "0" -a "$DUPLICATE" = "0"]; then
break
Если при выполнении подтверждения какой-либо части (например, при проверке длины строки или наличия только числовых значений) возникает ошибка, то в нижней части экрана отображается соответствующее сообщение.
Staff Number: Non Numeric or Too Many Numbers In Field
Чтобы подтвердить второе и третье поля, осуществляется аналогичный процесс. Часть, отвечающая за подтверждение, содержится в другом непрерывно выполняющемся цикле while. При этом вызывается функция characters. Эта функция проверяет, содержатся ли в поле только символы. Ниже фрагмент кода, в котором выполняется подтверждение имени:
while :
do
echo -n "Employee's First Name :"
read F_NAME
if [ "$F_NAME" != "" ]; then
if characters $F_NAME; then
F_NAME_PASS=0
else
F_NAME_PASS=1
fi
if length_check $F_NAME 20; then
LEN_PASS=0
else
LEN_PASS=1
fi
if [ "$LEN_PASS"="0" -a "$F_NAME_PASS"="0" ]; then
break
else
echo "Staff First Name: Non Character or Too Many Characters In Field"
continue_prompt
fi
else
echo "Staff First Name: No Input Detected, This Field Requires Characters"
continue_prompt
fi
done
Для подтверждения названия отдела (ниже) применяется конструкция case. Компания имеет пять отделов, а поле содержит только одно название. Обратите внимание, что названию каждого из отделов соответствуют три различных шаблона. Благодаря этому можно точно установить название отдела, если пользователь не помнит его наименование. Если совпадение с шаблоном найдено, пользователь прерывает выполнение конструкции case. Другие вводные данные перехватываются, в результате чего отображается список имеющихся отделов.
while :
do
echo -n "Company Department :"
read DEPART
case $DEPART in
ACCOUNTS|Accounts|accounts) break;;
SALES|Sales|sales) break;;
IT|It|it) break;;
CLAIMS|Claims|claims) break;;
SERVICES|Services|services) break;;
*) echo "Department: Accounts, Sales, IT, Claims, Services";;
esac
done
Когда все поля подтверждены, отображается приглашение с вопросом, следует ли сохранять эту запись. С этой целью применяется функция continue_promptYN, известная нам ранее, используя Y или N в качестве ответа. Если пользователь нажимает клавишу [Return](по скольку такой клавиши НЕТ, то Ctr+Z), можно также передать ответ, заданный по умолчанию.
Если пользователь выбирает N, производится просмотр блоков кода в конструкции if и выполнение сценария завершается. При вводе пользователем большого числа записей следует применить функцию, которая добавляет записи в теле цикла while. Тогда после добавления записи возврат в меню не происходит, а выполнение сценария не завершается.
Если пользователь выбирает Y, запись сохраняется. Для добавления записи в файл применяется следующий код
echo "$NUM:$F_NAME:$S_NAME:$DEPART" >> $DBFILE
Пользователь получает сообщение о том, что запись сохраняется в файле; при этом команда sleep приостанавливает выполнение сценария на одну секунду. Именно за это время пользователь сможет просмотреть сообщение.
Разделителем поля служит двоеточие. Затем файл сортируется по полю, содержащему фамилию, а поток вывода направляется в файл temp. После этого файл перемещается назад, в исходный файл DEFILE. Во время перемещений файла выполняется проверка кода завершения. При появлении каких-либо затруднений пользователь получает соответствующее сообщение.
ИТОГО:
#!/bin/bash
#dbase_add
#добавление записи
#игнорирование сигналов
trap "" 2 3 15
#файл temp содержит файлы
DBFILE=DBFILE
HOLD1=HOLD1.$$
#=================
read_a_char()
{
#read_a_char
#сохранение установок
SAVEDSTTY=`stty -g`
stty cbreak
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -cbreak
stty $SAVEDSTTY
}
#=================
continue_promptYN()
#вызов: continue_prompt "string to display" default_answer
{
# continue_prompt
_STR=$1
_DEFAULT=$2
# проверка наличия корректных параметров
if [ $# -lt 1 ]; then
echo "continue_prompt: I need a string to display"
return 1
fi
while :
do
echo -n "$_STR [Y..N] [$_DEFAULT]:"
read _ANS
#если пользователь нажимает клавишу ввода, устанавливается значение
#по умолчанию, затем определяется возвращаемое значение
: ${_ANS:=$_DEFAULT}
if [ "$_ANS" = "" ]; then
case $_ANS in
Y) return 0 ;;
N) return 1 ;;
esac
fi
# пользователь выбирает что–либо
case $_ANS in
y|Y|Yes|YES)
return 0
;;
n|N|No|NO)
return 1
;;
*) echo "Answer either Y or N, default ls $_DEFAULT"
;;
esac
echo $_ANS
done
}
#=================
continue_prompt()
{
# continue_prompt
echo -n "Hit any key to continue.."
DUMMY=`read_a_char`
}
#=================
length_check()
{
# length_check
# $1=строка для проверки длины $2=максимальная длина
_STR=$1
_MAX=$2
_LENGTH=`echo $_STR | awk '{print length ($0)}'`
if [ "$_LENGTH" -gt "$_MAX" ]; then
return 1
else
return 0
fi
}
#==================
a_number()
{
#a_number
#вызов: a_number $1=number
_NUM=$1
_NUM=`echo $1|awk '{if($0~/[^0-9]/) print "1"}'`
if [ "$_NUM" != "" ]
then
# ошибки
return 1
else
return 0
fi
}
#==================
characters()
#characters
#вызов: char_name string
{
_LETTERS_ONLY=$1
_LETTERS_ONLY=`echo $1 | awk '{if ($0~/[^a-zA-Z]/) print "1"}'`
if [ "$_LETTERS_ONLY" != "" ]
then
# ошибки
return 1
else
# содержит только символы
return 0
fi
}
#==================
check_duplicate()
{
#check_duplicate
#проверка дублирования номера служащего
#для вызова: check_duplicate строка
_CODE=$1
MATCH=`grep "$_CODE\>" $DBFILE`
echo $_CODE
if [ "$MATCH" = "" ]; then
return 0 # нет дубликата
else
return 1 # дубликат обнаружен
fi
}
#=================
add_rec()
{
# add_rec
# ==== STAFF NUMBER ====
while :
do
echo -n "Employee Staff Number :"
read NUM
if [ "$NUM" != "" ]; then
if a_number $NUM; then
NUM_PASS=0
else
NUM_PASS=1
fi
if length_check $NUM 10; then
LEN_PASS=0
else
LEN_PASS=1
fi
# проверка наличия дубликатов…
if check_duplicate $NUM; then
DUPLICATE=0
else
DUPLICATE=1
echo "Staff Number: There ls already a employee with this number"
continue_prompt
fi
if [ "$LEN_PASS" = "0" -a "$NUM_PASS" = "0" -a "$DUPLICATE" = "0" ]
then
break
else
echo "Staff Number: Non Numeric or Too Many Numbers In Field"
continue_prompt
fi
else
echo "Staff Number: No Input Detected, This Field Requires a Number"
continue_prompt
fi
done
# ==== Имя ====
while :
do
echo -n "Employee's First Name :"
read F_NAME
if [ "$F_NAME" != "" ]; then
if characters $F_NAME; then
F_NAME_PASS=0
else
F_NAME_PASS=1
fi
if
length_check $F_NAME 20; then
LEN_PASS=0
else
LEN_PASS=1
fi
# oбa условия должны быть истинными для выхода из этого цикла
if [ "$LEN_PASS" = "0" -a "$F_NAME_PASS" = "0" ]; then
break
else
echo "Staff First Name: Non Character or Too Many Characters In Field"
continue_prompt
fi
else
echo "Staff First Name: No Input Detected, This Field Requires Characters"
continue_prompt
fi
done
# ==== Фамилия ====
while :
do
echo -n "Employee's Surname :"
read S_NAME
if [ "$S_NAME" != "" ]; then
if characters $S_NAME; then
S_NAME_PASS=0
else
S_NAME_PASS=1
fi
if length_check $S_NAME 20; then
LEN_PASS=0
else
LEN_PASS=1
fi
if [ "$LEN_PASS" = "0" -a "$S_NAME_PASS" = "0" ]; then
break
else
echo "Staff Surname: Non Character or Too Many Characters In Field"
continue_prompt
fi
else
echo "Staff Surname: No Input Detected, This Field Requires Characters"
continue_prompt
fi
done
# ==== Отдел ====
while :
do
echo -n "Company Department :"
read DEPART
case $DEPART in
ACCOUNTS|Accounts|accounts) break;;
SALES|Sales|sales) break;;
IT|It|it) break;;
CLAIMS|Claims|claims) break;;
Services|SERVICES|services) break;;
*) echo "Department: Accounts, Sales, IT, Claims, Services";;
esac
done
}
# ==== Main ====
clear
echo -e "\t\t\tADD A EMPLOYEE RECORD"
if [ -s $DBFILE ]; then :
else
echo "Information: Creating new file to add employee records"
>$DBFILE
fi
add_rec
if continue_promptYN "Do You wish To Save This Record " "Y"; then
echo "$NUM:$F_NAME:$S_NAME:$DEPART" >> $DBFILE
echo "record saved"
sleep 1
sort +2 -t: $DBFILE > $HOLD1 2> /dev/null
if [ $? -ne 0 ]; then
echo "problems trying to sort the file, ...check it out"
exit 1
fi
mv $HOLD1 $DBFILE
if [ $? -ne 0 ]; then
echo "problems moving the temp sort file, ...check it out"
exit 1
fi
else
echo " record not saved"
sleep 1
fi
$ ~ dbase_add
ADD A EMPLOYEE RECORD
Employee Staff Number :45
45
Employee's First Name :Vasya
Employee's Surname :Sydoroff
Company Department :IT
Hit any key to continue.. record saved
$ ~ dbase_add
ADD A EMPLOYEE RECORD
Employee Staff Number :23
23
Employee's First Name :Lena
Employee's Surname :Ogurelova
Company Department :It-iiiii
Department: Accounts, Sales, IT, Claims, Services
Company Department :Sales
Do You wish To Save This Record [Y..N] [Y]:y
record saved
$ ~ dbase_add
ADD A EMPLOYEE RECORD
Employee Staff Number :123
123
Employee's First Name :Greesha
Employee's Surname :Chumnoy
Company Department :IT
Do You wish To Save This Record [Y..N] [Y]:y
record saved
$ ~ cat DBFILE
123:Greesha:Chumnoy:IT
23:Lena:Ogurelova:Sales
21:Petya:Petroff:it
45:Vasya:Sydoroff:IT
$ ~
Удаление записей
Прежде чем удалить запись из файла, ее нужно сначала отобразить для пользователя, чтобы он мог убедиться,что именно эта запись подлежит удалению. После получения подтверждения можно приступать к удалению записи.
При удалении записи выполняются следующие операции:
Поиск записи.
Отображение записи.
Подтверждение процедуры удаления.
Обновление файла.
Чтобы найти запись, следует воспользоваться полем, где содержатся фамилии. После того как пользователь введет фамилию, по которой ведется поиск, можно приступать к обработке. Можно применить команду grep или утилиту awk.Но поскольку данный файл, скорее всего, содержит не более 100 записей, просмотрим его и определим наличие совпадений. Если же файл содержит более двух сотен записей, желательно воспользоваться утилитой awk. Это значительно быстрее, чем просмотр файла; к тому же утилита awk более удобна при разделении полей, принадлежащих переменным.
Чтобы применить команду grep или утилиту awk, можно выполнить поиск в файле DBFILE:
echo "enter the surname to search "
read STR
#при работе с awk используйте команду
awk -F: '/$STR/' DBFILE
#при работе с grep используйте команду
grep "$STR" DBFILE
#либо команду
grep "$STR\ >" DBFILE
При использовании утилиты awk (в отличии от grep) переменную заключают в одинарные кавычки.
Если не придерживаться этого условия, не выполняется возврат данных.
Чтобы разделить поля, можно каждому полю назначить переменные (в нашем случае разделителем полей служит двоеточие). Переменной Ifs нужно присвоить значение двоеточия. Если не сделать этого, запись нельзя будет просматривать. При изменении значения переменной ifs желательно сначала сохранить установки. Благодаря этому их можно будет восстановить по завершении работы сценария.
Чтобы сохранить значения переменной ifs, примените следующую команду: SAVEDIFS=$IFS
Заменить значение переменной ifs двоеточием можно, выполнив команду: IFS=:
По завершении работы с переменной IFS вы можете легко восстановить ее значение: IFS=$SAVEDIFS
С помощью функции getrec можно выполнить полномасштабный поиск
(этой функции не передаются параметры).
get_rec ()
{
# get_rec
clear
echo -n "Enter the employee surname :"
read STR
if [ "$STR" = "q" ]; then
return 1
fi
REC=0
MATCH=no
if [ "$STR" != "" ]; then
while read CODE F_NAME S_NAME DEPART
do
REC=`expr $REC + 1`
tput cup 3 4
echo -n " searching record.. $REC"
if [ "$S_NAME" = "$STR" ]; then
MATCH=yes
display_rec
break
else
continue
fi
done<DBFILE
else
echo "Enter a surname to search for or q to quit"
fi
if [ "$MATCH" = "no" ]; then
no_recs
fi
}
Пользователь может ввести фамилию или же указать q для завершения выполнения задания. Если указывается фамилия, производится проверка для того, чтобы удостовериться, что фамилия представляет собой вводные данные. Имейте в виду, что удобнее воспользоваться следующей проверкой: if [ "$STR"! = "" ]; then
Но не такой: [ -z $STR ]
При выборе первой проверки пользователю достаточно нажать на клавишу [Return (Ctrl+Z)], чтобы выполнить команду trap.
Enter the employee surname :^Z
[2]+ Остановлен dbase_del
$ ~
Во втором случае устанавливается лишь наличие строки нулевой длины.
При считывании значения каждого поля файла используются значащие наименования переменных. Затем при считывании записей применяется счетчик. Действительно, такой прием отражается только на внешней форме сценария и позволяет контролировать процесс поиска записей. Если совпадение найдено, вызывается другая процедура, которая приводит к отображению значений полей. Команда break позволяет прекратить выполнение цикла. Если совпадение не обнаружено, сценарий продолжает выполняться до следующей итерации цикла.
Когда устанавливается соответствие, пользователь получает запрос, действительно ли нужно удалить запись. По умолчанию ответ будет nо.
if continue_promptYN "Do You Wish To DELETE This Record" "N"; then
tput setaf 1; echo "REMOVED OK !"; tput sgr0
grep -v $STR DBFILE >$HOLD1 2> /dev/null
if [ $? -ne 0 ]; then
echo "Problems creating temp file $HOLD1.. check it out"
exit 1
fi
Удаление записи выполняется выполнением команды grep с опцией -v. В этом случае с помощью строки STR отображаются все не совпадающие поля. (Эта строка содержит фамилию, которая запрашивается пользователем при удалении записи.)
Поток данных вывода для команды grep перенаправляется во временный файл, где выполняется сортировка. Затем временный файл заменяет исходный файл DBFILE.
При реализации всех перемещений данных выполняется проверка с помощью кода завершения последней команды.
ИТОГО:
#!/bin/sh
#dbase_del
#удаление записи
#перехват сигналов
trap "" 2 3 15
#Файл данных
DBFILE=DBFILE
#временные файлы
HOLD1=HOLD1.$$
HOLD2=HOLD2.$$
continue_promptYN()
{
#continue_prompt
_STR=$1
_DEFAULT=$2
#проверка наличия правильных параметров
if [ $# -lt 1 ]; then
echo "continue_prompt: I need a string to display"
return 1
fi
while :
do
echo -n "$_STR [Y..N] [$_DEFAULT]:"
read _ANS
: ${_ANS:=$_DEFAULT}
if [ "$_ANS" = "" ]; then
case $_ANS in
Y) return 0 ;;
N) return 1 ;;
esac
fi
case $_ANS in
у|Y|Yes|YES)
return 0
;;
n|N|No|NO)
return 1
;;
*) echo "Answer either Y or N, default is $_DEFAULT"
;;
esac
done
}
display_rec()
{
#display_rec
#можно воспользоваться командой cat << документ здесь
tput cup 5 5
echo "EMPLOYEE NO : $CODE"
echo "FIRST NAME : $F_NAME"
echo "SURNAME : $S_NAME"
echo "DEPARTMENT : $DEPART"
echo -e "\n\n"
}
no_recs ()
{
# no_recs
echo -e "\n\nSorry could not find a record with the name $STR"
}
get_rec ()
{
# get_rec
clear
echo -n "Enter the employee surname :"
read STR
if [ "$STR" = "q" ]; then
return 1
fi
REC=0
MATCH=no
if [ "$STR" != "" ]; then
while read CODE F_NAME S_NAME DEPART
do
REC=`expr $REC + 1`
tput cup 3 4
echo -n " searching record.. $REC"
if [ "$S_NAME" = "$STR" ]; then
MATCH=yes
display_rec
break
else
continue
fi
done <DBFILE
else
echo "Enter a surname to search for or q to quit"
fi
if [ "$MATCH" = "no" ]; then
no_recs
fi
}
#==== MAIN ====
SAVEDIFS=$IFS
IFS=:
get_rec
if [ "$MATCH" = "yes" ]; then
if continue_promptYN "Do You Wish To DELETE This Record" "N"; then
tput setaf 1; echo "REMOVED OK !"; tput sgr0
grep -v $STR DBFILE >$HOLD1 2> /dev/null
if [ $? -ne 0 ]; then
echo "Problems creating temp file $HOLD1..check it out"
exit 1
fi
mv $HOLD1 DBFILE
if [ $? -ne 0 ]; then
echo "Problems moving temp file..check it out"
exit 1
fi
# сортировка файла после изменений
sort +2 -t: $DBFILE >$HOLD2 2> /dev/null
if [ $? -ne 0 ]; then
echo "problems trying to sort the file..check it out"
exit 1
fi
mv $HOLD2 $DBFILE
if [ $? -ne 0 ]; then
echo "problems moving the temp sort file..check it out"
exit 1
fi
else
tput setaf 2; echo "NO deletion !"; tput sgr0
# удаление отсутствует
fi # если нужно удалить
fi # если совпадает
# восстановление установок IFS
IFS=$SAVEDIFS
$ ~ cat DBFILE
777:Agent:Smith:IT
7654:Lena:Непомнящая:Sales
789:Вася:Пистолетов:it
$ ~ dbase_del
Enter the employee surname :Пистолетов
searching record.. 3
EMPLOYEE NO : 789
FIRST NAME : Вася
SURNAME : Пистолетов
DEPARTMENT : it
Do You Wish To DELETE This Record [Y..N] [N]:Y
REMOVED OK !
$ ~
Добавлением в вывод: tput setaf [...] , возможно сделать скрипт более наглядным.
(Что возможно делать и не стоит.)
Обновление записей
Когда обнаруживается корректная запись, все переменные поля записи с помощью переменной, выполняющей присваивание по умолчанию, назначаются переменной temp:
: [переменная, заданная по умолчанию:=переменная
Пользователь может просто нажать клавишу [Return](Ctrl+Z, Enter) для тех полей, значения которых изменять нежелательно. Затем переменная temp заменяется значением, заданным по умолчанию. Для выполнения произвольных обновлений можно просто вводить в соседние поля новые значения.
echo -n -e "EMPLOYEE NO: $CODE\n"
echo -n "FIRST NAME : [$F_NAME] >"
read _F_NAME
: ${_FNAME:=$P_NAME}
..................
Для реального обновления файла достаточно снова воспользоваться командой grep с опцией -v. Все записи обновляются по отдельности и перенаправляются во временный файл. Номер служащего(табельный номер) задается ввиде строки команды grep:
grep -v $C0DE $DBFILE >$HOLD1
Пользователь получает запрос, нужно ли сохранять данную запись. Если ответ положителен, обновленная запись также добавляется во временный файл. Затем временный файл перемещается в исходный файл DEFILE.
echo "$CODE:$_F_NAME:$_S_NAME:$_DEPART" >> $HOLD1
mv $HOLD1 $DBFILE
После этого выполняется сортировка файла с помощью потока вывода, который сначала перенаправлялся во временный файл, затем перемещается обратно — в исходный файл DBFILE. Проверки кода завершения выполняются во время упомянутых действий с файлами, и пользователю выдаются сообщения об имеющихся затруднениях.
Полный сценарий, выполняющий обновление записей:
$ vim dbase_change
#!/bin/bash
# dbase_change
#обновление записи
#игнорирование сигналов
trap "" 2 3 15
#временные файлы
DBFILE=DBFILE
HOLD1=HOLD1.$$
HOLD2=HOLD2.$$
continue_promptYN()
{
#continue_prompt
_STR=$1
_DEFAULT=$2
#проверим, что параметры верны
if [ $# -lt 1 ]; then
echo "continue_prompt: I need a string to display"
return 1
fi
while :
do
echo -n "$_STR [Y..N] [$_DEFAULT]:"
read _ANS
: ${_ANS:=$_DEFAULT}
if [ "$_ANS" = "" ]; then
case $_ANS in
Y) return 0
;;
N) return 1
;;
esac
fi
case $_ANS in
y|Y|Yes|YES) return 0
;;
n|N|No|NO) return 1
;;
*) echo "Answer either Y or N, default is $_DEFAULT"
;;
esac
done
}
display_rec()
{
#отображение_записи
#можно применить команду cat « документ, но нежелательно
tput cup 5 5
echo "EMPLOYEE NO: $CODE"
echo "FIRST NAME : $F_NAME"
echo "SURNAME : $S_NAME"
echo "DEPARTMENT : $DEPART"
echo -e "\n\n"
}
no_recs()
{
# no_recs
echo -e "\n\nSorry could not find a record with the name $STR"
}
get_rec ()
{
# get_rec
clear
echo -n "Enter the employee surname :"
read STR
if [ "$STR" = "q" ]; then
return 1
fi
REC=0
MATCH=no
if [ "$STR" != "" ]; then
while read CODE F_NAME S_NAME DEPART
do
REC=`expr $REC + 1`
tput cup 3 4
echo -n " searching record.. $REC"
if [ "$S_NAME" = "$STR" ]; then
MATCH=yes
display_rec
break
else
continue
fi
done <$DBFILE
else
echo "Enter a surname to search for or q to quit"
fi
if [ "$MATCH" = "no" ]; then
no_recs
fi
}
# ==== MAIN ====
SAVEDIFS=$IFS
IFS=:
get_rec
if [ "$MATCH" = "yes" ]; then
if continue_promptYN "Is this the record you wish to amend" "Y"
then
echo "amending"
# нельзя изменить код служащего
echo -n -e "EMPLOYEE NO: $CODE\n"
echo -n "FIRST NAME : [$F_NAME] >"
read _F_NAME
: ${_FNAME:=$F_NAME}
echo -n "SURNAME : [$S_NAME] >"
read _S_NAME
: ${_S_NAME:=$S_NAME}
echo -n "DEPARTMENT : [$DEPART] >"
read _DEPART
: ${_DEPART:=$DEPART}
grep -v $CODE $DBFILE >$HOLD1
if [ $? -ne 0 ]; then
echo "Problems creating temporary file..check it out"
exit 1
fi
if continue_promptYN "Ready to save this record" "Y"; then
echo "$CODE:$_F_NAME:$_S_NAME:$_DEPART" >> $HOLD1
mv $HOLD1 $DBFILE
if [ $? -ne 0 ]; then
echo "Problems moving temporary file, …check it out"
fi
tput setaf 2; echo " Record Amended"; tput sgr0
# сортировка файла после изменений
sort +2 -t: $DBFILE >$HOLD2 2> /dev/null
if [ $? -ne 0 ]; then
echo "problems trying to sort the file..check it out"
exit 1
fi
mv $HOLD2 $DBFILE
if [ $? -ne 0 ]; then
echo "problems moving the temp sort file..check it out"
exit 1
fi
else #если обновление прерывается
echo " Amend aborted"
exit 0
fi
else # если не выполняется обновление
echo " No amending"
# нет удаления
fi # если желательно удалить
fi # если имеется совпадение
IFS=$SAVEDIFS
Вывод:
$ ~ cat DBFILE
456:Pavel:Peskoff:Accounts
777:Agent:Smith:IT
56565:Екатерина:Катина:it
7654:Lena:Непомнящая:Sales
123:Роман:Романов:Services
89:Анжелика:Стулова:Sales
$ ~ dbase_change
Enter the employee surname :Стулова
searching record.. 6
EMPLOYEE NO: 89
FIRST NAME : Анжелика
SURNAME : Стулова
DEPARTMENT : Sales
Is this the record you wish to amend [Y..N] [Y]:Y
amending
EMPLOYEE NO: 89
FIRST NAME : [Анжелика] >Angelina
SURNAME : [Стулова] >Jolie
DEPARTMENT : [Sales] >
Ready to save this record [Y..N] [Y]:Y
Record Amended
$ ~ cat DBFILE
89:Angelina:Jolie:Sales
456:Pavel:Peskoff:Accounts
777:Agent:Smith:IT
56565:Екатерина:Катина:it
7654:Lena:Непомнящая:Sales
123:Роман:Романов:Services
$ ~
Просмотр записей
$ ~ vim dbase_view
#!/bin/bash
#dbase_view
#просмотр записей
#игнорирование сигналов
trap "" 2 3 15
#временные файлы
HOLD1=HOLD1.$$
DBFILE=DBFILE
continue_promptYN ()
{
#continue_prompt
_STR=$1
_DEFAULT=$2
#проверим, что параметры верны
if [ $# -lt 1 ]; then
echo "continue_prompt: I need a string to display"
return 1
fi
while :
do
echo -n "$_STR [Y..N] [$_DEFAULT]:"
read _ANS
: ${_ANS:=$_DEFAULT}
if [ "$_ANS" = "" ]; then
case $_ANS in
Y) return 0 ;;
N) return 1 ;;
esac
fi
case $_ANS in
у|Y|Yes|YES)
return 0
;;
n|N|No|NO)
return 1
;;
*) echo "Answer either Y or N, default ls $_DEFAULT"
esac
done
}
display_rec()
{
#diaplay_rec
#можно применить команду cat <<.
tput cup 5 5
echo "EMPLOYEE NO: $CODE"
echo "FIRST NAME : $F_NAME"
echo "SURNAME : $S_NAME"
echo "DEPARTMENT : $DEPART"
echo -e "\n\n"
}
no_recs ()
{
# no_recs
echo -e "\n\nSorry could not find a record with the name $STR"
}
get_rec ()
{
# get_rec
clear
echo -n "Enter the employee surname to view or all for all records:"
read STR
if [ "$STR" = "q" ] ; then
return 1
fi
if [ "$STR" = "all" ]; then
# просмотр всех записей
echo "Surname Name Employee Code"
echo "__________________________________________"
cat $DBFILE |awk -F: '{print $2"\t\t"$3"\t\t"$1"\t"$4}' | more
return 0
fi
REC=0
REC=0
MATCH=no
if [ "$STR" != "" ]; then
while read CODE F_NAME S_NAME DEPART
do
REC=`expr $REC + 1`
tput cup 3 4
echo -n " searching record.. $REC"
if [ "$S_NAME" = "$STR" ]; then
# обнаружено имя
MATCH=yes
display_rec
break
else
continue
fi
done <$DBFILE
else
echo "Enter a surname to search for or q to quit"
fi
if [ "$MATCH" = "no" ]; then
no_recs
fi
}
# ==== MAIN ====
SAVEDIFS=$IFS
IFS=:
get_rec
if [ "$MATCH" = "yes" ]; then
if continue_promptYN "Do You Wish To Print This Record" "N"; then
lpr <<- MAYDAY
RECORD No: $REC
EMPLOYEE NUMBER : $CODE
EMPLOYEE NAME : $F_NAME
EMPLOYEE SURNAME : $S_NAME
EMPLOYEE DEPARTMENT : $DEPART
MAYDAY
else
echo "No print of $S_NAME"
# не отображается
fi # если желательно отображение
fi # если имеется совпадение
IFS=$SAVEDIFS
Вывод:
$ ~ dbase_view
Enter the employee surname to view or all for all records:all
Surname Name Employee Code
______________________________________
Johny BeGood 567 IT
Анжела Jolie 897 Sales
Pavel Peskoff 456 Accounts
Agent Smith 777 IT
$ ~ dbase_view
Enter the employee surname to view or all for all records:Smith
searching record.. 4
EMPLOYEE NO: 777
FIRST NAME : Agent
SURNAME : Smith
DEPARTMENT : IT
Do You Wish To Print This Record [Y..N] [N]:N
No print of Smith
$ ~