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

[me@linuxbox ~]$ export PS4='$LINENO + '

[me@linuxbox ~]$ trouble

5 + number=1

7 + '[' 1 = 1 ']'

8 + echo 'Number is equal to 1.'

Number is equal to 1.

Выполнить трассировку только выбранного фрагмента сценария можно с помощью команды set с параметром -x:

#!/bin/bash

# trouble: сценарий для демонстрации распространенных видов ошибок

number=1

set -x # Включить трассировку

if [ $number = 1 ]; then

        echo "Number is equal to 1."

else

    echo "Number is not equal to 1."

fi

set +x # Выключить трассировку

Здесь мы использовали команду set с параметром -x, чтобы включить трассировку, и с параметром +x, чтобы выключить ее. Этот прием используется для исследования сразу нескольких проблемных фрагментов в сценарии.

Исследование значений в процессе выполнения

Часто вместе с трассировкой полезно выводить содержимое переменных, чтобы иметь более полное представление о действиях сценария. Обычно для этого используются дополнительные инструкции echo:

#!/bin/bash

# trouble: сценарий для демонстрации распространенных видов ошибок

number=1

echo "number=$number" # ОТЛАДКА

set -x # Включить трассировку

if [ $number = 1 ]; then

echo "Number is equal to 1."

else

echo "Number is not equal to 1."

fi

set +x # Выключить трассировку

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

Заключительное замечание

В этой главе мы рассмотрели несколько проблем, с которыми можно столкнуться в процессе разработки сценариев. Конечно, таких проблем несоизмеримо больше. Приемы, описанные здесь, помогут вам в поиске наиболее распространенных видов ошибок. Отладка — это искусство предотвращения ошибок (за счет постоянного тестирования в ходе разработки) и их поиска (путем эффективного использования приемов трассировки), которое дается только с опытом.

31. Управление потоком выполнения: ветвление с помощью case

В этой главе мы продолжим знакомство с инструментами управления потоком выполнения. В главе 28 мы сконструировали простое меню и реализовали логику обработки выбора его пунктов пользователем. Для этого использовалась серия команд if, выясняющих, какой из возможных вариантов выбран. Такие конструкции часто можно увидеть в программах, причем так часто, что в некоторых языках программирования (включая командную оболочку) был реализован механизм управления потоком выполнения для случаев с множеством альтернативных вариантов.

case

Командная оболочка bash поддерживает составную команду выбора из нескольких вариантов, которая называется case. Она имеет следующий синтаксис:

case слово in

        [шаблон [| шаблон]...) команды ;;]...

esac

Взгляните еще раз, как программа read-menu из главы 28 обрабатывает выбор пользователя:

#!/bin/bash

# read-menu: программа вывода системной информации,

#            управляемая с помощью меню

clear

echo "

Please Select:

1. Display System Information

2. Display Disk Space

3. Display Home Space Utilization

0. Quit

"

read -p "Enter selection [0-3] > "

if [[ $REPLY =~ ^[0-3]$ ]]; then

        if [[ $REPLY == 0 ]]; then

                echo "Program terminated."

                exit

        fi

        if [[ $REPLY == 1 ]]; then

                echo "Hostname: $HOSTNAME"

                uptime

                exit

        fi

        if [[ $REPLY == 2 ]]; then

                df -h

                exit

        fi

        if [[ $REPLY == 3 ]]; then

                if [[ $(id -u) -eq 0 ]]; then

                        echo "Home Space Utilization (All Users)"

                        du -sh /home/*

                else

                        echo "Home Space Utilization ($USER)"

                        du -sh $HOME

                fi

                exit

        fi

else

        echo "Invalid entry." >&2

        exit 1

fi

С помощью case можно сделать логику выбора немного проще:

#!/bin/bash

# case-menu: программа вывода системной информации,

#            управляемая с помощью меню

clear

echo "

Please Select:

1. Display System Information

2. Display Disk Space

3. Display Home Space Utilization

0. Quit

"

read -p "Enter selection [0-3] > "

case $REPLY in

        0)      echo "Program terminated."

                exit

                ;;

        1)      echo "Hostname: $HOSTNAME"

                uptime

                ;;

        2)      df -h

                ;;

        3)     if [[ $(id -u) -eq 0 ]]; then

                        echo "Home Space Utilization (All Users)"

                        du -sh /home/*

                else

                        echo "Home Space Utilization ($USER)"

                        du -sh $HOME

                fi

                ;;

        *)      echo "Invalid entry" >&2

                exit 1

                ;;

esac

Команда case берет значение слова — в данном примере значение переменной REPLY — и затем сопоставляет его с указанными шаблонами. Найдя соответствие, она выполняет команды, связанные с найденным шаблоном. После нахождения соответствия сопоставление с нижележащими шаблонами уже не производится.

Шаблоны

Шаблоны обрабатываются командой case точно так же, как пути механизмом подстановки. Шаблоны завершаются символом ). В табл. 31.1 перечислены некоторые допустимые шаблоны.

Таблица 31.1. Примеры шаблонов в команде case

Шаблон

Описание

a)

Соответствует, если слово содержит a

[[:alpha:]])

Соответствует, если слово содержит единственный алфавитный символ

???)

Соответствует, если слово содержит ровно три символа

*.txt)

Соответствует, если слово заканчивается символами .txt

*)

Соответствует любому значению слова. Считается хорошей практикой включать этот шаблон в команду case последним, чтобы перехватывать любые значения слова, не соответствующие ни одному из предыдущих шаблонов, то есть чтобы перехватывать любые недопустимые значения

Следующий пример демонстрирует работу шаблонов:

#!/bin/bash

read -p "enter word > "

case $REPLY in

        [[:alpha:]])     echo "is a single alphabetic character." ;;

        [ABC][0-9])      echo "is A, B, or C followed by a digit." ;;

        ???)             echo "is three characters long." ;;

100
{"b":"568756","o":1}