Литмир - Электронная Библиотека
Содержание  
A
A

read Summary

if get -o /tmp/put.a$$ $1 # previous version

then                      # merge pieces

 cp $1 /tmp/put.b$$       # current version

 echo"@@@ `getname` `date` $Summary" >>/tmp/put.b$$

 diff -e $1 /tmp/put.a$$ >>/tmp/put.b$$   # latest diffs

 sed -n '/^@@@/,$p' <$HIST >>/tmp/put.b$$ # old diffs

 overwrite $HIST cat /tmp/put.b$$ # put it back

else # make a new one

 echo "put: creating $HIST"

 cp $1 $HIST

 echo "@@@ `getname` `date` $Summary" >>$HIST

fi

rm -f /tmp/put.[ab]$$

После считывания одной строки сводки команда

put
обращается к
get
для получения предыдущей версии файла из файла истории. Флаг
команды
get
указывает на переключение выходного файла. В том случае, когда
get
не может найти файл истории, она возвращает код завершения ошибки, и
put
создает файл истории. Если файл истории существует, то в командах после
then
создается временный файл такого формата: самая последняя версия, строка
@@@
, команды редактора для преобразования этой версии в предыдущую, старые команды редактора и строки В конце временный файл копируется в файл истории с помощью команды
overwrite
.

Команда

get
в отличие от
put
включает флаги:

# get: extract file from history

PATH=/bin:/usr/bin

VERSION=0

while test "$1" != ""

do

 case "$1" in

 -i) INPUT=$2; shift ;;

 -o) OUTPUT=$2; shift ;;

 -[0-9]) VERSION=$1 ;;

 -*) echo "get: Unknown argument $i" 1>&2; exit 1 ;;

 *) case "$OUTPUT" in

 "") OUTPUT=$1 ;;

 *) INPUT=$1.H ;;

 esac

 esac

 shift

done

OUTPUT=${OUTPUT?"Usage: get [-o outfile] [-i file.H] file"}

INPUT=${INPUT-$OUTPUT.H}

test -r $INPUT || { echo "get: no file $INPUT" 1>&2; exit 1; }

trap 'rm -f /tmp/get.[ab]$$; exit 1' 1 2 15

# split into current version and editing commands

sed <$INPUT -n '1,/^@@@/w /tmp/get.a'$$'

/^@@@/,$w /tmp/get.b'$$

# perform the edits

awk </tmp/get.b$$ '

 <a href="">/^@@@/</a> { count++ }

 !/^@@@/ &amp;&amp; count &gt; 0 &amp;&amp; count &lt;= - &quot;$VERSION&quot;

 END { print &quot;$d&quot;; print &quot;w&quot;, &quot;'$OUTPUT'&quot; }

' | ed - /tmp/get.a$$

rm -f /tmp/get.[ab]$$

Флаги выполняют обычные функции:

-i
и
задают переключение входного и выходного потоков, —
-[0-9]
определяет версию:
-0
— новая версия (значение по умолчанию),
-1
— предыдущая версия и т.д.). Цикл по аргументам организуется с помощью команд
while
,
test
и
shift
, а не с помощью
for
, поскольку некоторые флаги (
-i
,
) используют еще один аргумент, и поэтому нужно сдвигать их командой
shift
, которая плохо согласуется с циклом
for
, если она находится внутри него. Флаг редактора
ed
отключает вывод числа символов, обычный при чтении и записи в файл.

Строка

test -r $INPUT || {echo &quot;get: no file $INPUT&quot; 1&gt;&amp;2; exit 1;}

эквивалентна конструкции

if test ! -r $INPUT

then

 echo &quot;get: no file $INPUT&quot; 1&gt;&amp;2

 exit 1

fi

(такую конструкцию мы использовали в команде

put
), но запись ее короче, и она понятнее программистам, хорошо знакомым с операцией
||
. Команды, заключенные между
{
и
}
, выполняются не порожденным, а исходным интерпретатором. Это необходимо для того, чтобы команда
exit
обеспечивала выход из
get
, а не из порожденного интерпретатора. Символы
{
и
}
подобны
do
и
done
— они приобретают специальные значения, если следуют за точкой с запятой, символом перевода строки или другим символом завершения команды.

В заключение мы рассмотрим те команды в

get
, которые и решают задачу. Вначале с помощью редактора
sed
файл истории разбивается на две части, содержащие самую последнюю версию и набор команд редактирования. Затем в
awk
-программе обрабатываются команды редактирования. Строки
@@@
подсчитываются (но не печатаются), и до тех пор, пока их число не превышает номера нужной версии, команды редактирования пропускаются (напомним, что действие, принятое по умолчанию, в
awk
-программе сводится к выводу входной строки). К командам редактирования из файла истории добавлены еще две команды
ed
:
$d
удаляет одну строку
@@@
, которую редактор
sed
оставил в текущей версии, а команда
w
помещает файл в отведенное ему место. Команда
overwrite
здесь не нужна, поскольку в
get
изменяется только версия файла, а не сам файл истории.

73
{"b":"248117","o":1}