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

$ ~

Удаление записей

Прежде чем удалить запись из файла, ее нужно сначала отобразить для пользователя, чтобы он мог убедиться,что именно эта запись подлежит удалению. После получения подтверждения можно приступать к удалению записи.

При удалении записи выполняются следующие операции:

    1. Поиск записи.

    2. Отображение записи.

    3. Подтверждение процедуры удаления.

    4. Обновление файла.

Чтобы найти запись, следует воспользоваться полем, где содержатся фамилии. После того как пользователь введет фамилию, по которой ведется поиск, можно приступать к обработке. Можно применить команду 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

$ ~

---------------------------

«Garbage In - Garbage Out» --->> «GIGO»

---------------------------