Назад

Некоторые приемы программирования
Пример 1
Пример 2
Пример 3


 

Некоторые приемы программирования

Описанные ниже некоторые приемы программирования, возможно, помогут Вам в решении Вашей задачи. В большинстве случаев Вам понадобятся команды обработки текстов и потоковый редактор sed. Информацию о файлах, как правило, можно получить от команды ls и других команд файловой системы. Краткие описания всех необходимых команд есть в нашей справочной системе.


 

Пример 1

Задание
Проверить, работает ли в сети заданный пользователь. Если да - отправить ему сообщение по write. Если пользователя нет в сети или он заблокировал терминал, - отправить сообщение по mail.

Формат применения этой команды должен быть:

    команда пользователь...

Ниже мы приводим текст скрипта (мы назвали его ex7_1) с подробными комментариями.

      #!/bin/bash2
      # ============================================================== #
      # Скрипт ex7_1: отправка сообщения/письма заданным пользователям #
      # ============================================================== #
      # Комментарий !/bin/bash2 описывает местонахождения командного
      # интерпретатора shell. Он помогает системе найти интерпретатор,
      # а также помогает команде file определить тип файла-скрипта.
      # В большинстве случаев он не является обязательным, но является 
      # "правилом хорошего тона" в программировании.
      # =======================================================
      #
      # Текст сообщения/письма заносится в файл temp01
      # Обратите внимание: временный файл размещается в домашнем
      # каталоге пользователя.
      echo Это тестовое сообщение > $HOME/temp01 
      echo для проверки связи из скрипта. >>$HOME/temp01
      echo Желаю успеха! >>$HOME/temp01
      echo ap10999 >>$HOME/temp01
      # ========================================================
      # Параметры команды представляют собой список имен пользователей.
      # Следующим оператором организуется цикл, который выполняется до
      # тех пор, пока остаются необработанные параметры.
      while [ $# -ne 0 ] 
      do
        # ======================================================
        # Значение 1-го параметра присваивается переменной us
        us=$1
        # ======================================================
        # Удаляется файл temp02. Обратите внимание: диагностика команды
        # rm подавляется (направляется в "системную корину"). Эта диагностика
        # может сообщать о том, что удаляемого файла не существует - 
        # она нам не нужна.
        rm $HOME/temp02 2>/dev/null
        # ======================================================
        # Попытка выдачи сообщения пользователю.
        # Системный ввод команды write направляется на файл temp01.
        # Если не удается установить соединение с пользователем (пользователя
        # нет в системе или он заблокировал свой терминал) команда write
        # выводит диагностическое сообщение (мы его подавляем) и
        # возвращает false.
        if write $us <$HOME/temp01 2>/dev/null
          then
          # ====================================================
          # Если сообщение прошло - OK! выводим на свой терминал
          # сообщение об этом, и - "обработка пользователя" закончена.
          echo "Пользователю $us отправлено сообщение"  
        else 
          # ====================================================
          # Если сообщение не прошло - попытка отправки письма
          # Системный ввод команды mail направляется на файл temp01.
          # Команда mail всегда возвращает true. Она только запускает
          # дочерний процесс sendmail, и, если отправка письма не удалась,
          # это будет выяснено только в дочернем процессе, которая выдаст
          # диагностику, эту диагностику перенаправляем во временный
          # файл temp02.
          mail $us <$HOME/temp01 >$HOME/temp02
          # ====================================================
          # Ожидаем 1 сек, чтобы дочерний процесс успел записать
          # в файл temp02 сообщение о том, что письмо не отправлено
          sleep 1
          # ====================================================
          # Проверяем, есть ли что-нибудь в файле temp02
          if test -s $HOME/temp02
            then
            # ==================================================
            # Если файл temp02 не пустой - пользователь не найден
            echo "Пользователь $us не найден" 
            # ==================================================
            # в этом случае письмо попадает в файл dead.letter,
            # который нам не нужен
            rm $HOME/dead.letter 2>/dev/null
          else 
            # ==================================================
            # Если файл temp02 пустой - письмо отправлено
            echo "Пользователю $us отправлено письмо" 
          # ====================================================
          # Конец условия if test -s $HOME/temp02
          fi
        # ======================================================
        # Конец условия if write $us ...
        fi
        # ======================================================
        # Сдвиг списка параметров
        shift
      # ========================================================
      # Конец цикла while
      done
      # ========================================================
      # После выхода из цикла
      # Удаляются временные файлы
      rm $HOME/dead.letter 2>/dev/null
      rm $HOME/temp01 2>/dev/null
      rm $HOME/temp02 2>/dev/null
      # ======== Конец скрипта ex7_1 ================================= #

Ниже приведен образец выполнения созданной команды:


bash2-2.05$ sh ex1_7 ap10999 ap10998 ap1097
Пользователю ap10999 отправлено сообщение
Пользователю ap10998 отправлено письмо
Пользователь ap1097 не найден
bash2-2.05$


 

Пример 2

Задание
Вывести названия всех файлов в заданном каталоге, имеющих одинаковую первую строку.

Формат применения этой команды должен быть:

    команда каталог...

Cкрипт назван ex7_2, его текст с подробными комментариями приводится ниже.

      #!/bin/bash2
      # ============================================================== #
      # Скрипт ex7_2: поиск совпадающих первых строк                   #
      # ============================================================== #
      # ========================================================
      # Запоминаем текущий каталог
      mydir=`pwd`
      # ========================================================
      # Параметры команды представляют собой список каталогов.
      # Следующим оператором организуется цикл, который выполняется до
      # тех пор, пока остаются необработанные параметры.
      while [ $# -ne 0 ]
        do
        # ======================================================
        # Переход в каталог, задаваемый 1-м параметром;
        # диагностика направляется во временный файл
        cd $1 2>$HOME/temp01
        # ======================================================
        # Проверка - не пустой ли файл с диагностикой 
        if test -s $HOME/temp01
          then
          # ====================================================
          # Если есть диагностика - каталог недоступен
          echo "Каталог $1 недоступен/не существует"
          # ====================================================
          # Переход к следующему параметру
          shift
          # ====================================================
          # Пропуск остатка тела цикла
          continue
          fi
        # ======================================================
        # Мы вошли в заданный каталог
        echo "Каталог: $1"
        # ======================================================
        # Выбираются файлы размером больше 0,
        # список файлов направляется в поток
        find -size +0c -type f | 
        # ======================================================
        # Файлы в списке выведены с указанием каталога ./,
        # от этих символов нужно избавиться;
        # результат записывается во временный файл
        sed 's/.\///' >$HOME/temp01
        # ======================================================
        # Цикл пока в файле temp01 что-то остается
        while test -s $HOME/temp01
          do
          # ====================================================
          # Выбирается в переменную $f1 первая строка из
          # временного файла - имя очередного файла
          f1=`head -n1 $HOME/temp01`
          # ====================================================
          # Выбирается в переменную $s1 первая строка из
          # выбранного файла 
          s1=`head -n1 $f1`
          # ====================================================
          # $n - признак того, что совпадение строк не найдено
          # $m - номер второго файла из списка
          n="no"; m=2;
          # ====================================================
          # Бесконечный цикл - выход по break
          while [ 1 ]
            do
            # ==================================================
            # Выбирается $m-я строка из списка файлов - имя файла
            f2=`sed -n ''$m'p' $HOME/temp01`
            # ==================================================
            # Если выбрана пустая строка - список файлов закончился
            if [ "$f2" = "" ]; then
              # ================================================
              # в этом случае - выход из цикла
              break
              # ================================================
              # Конец условия if [ "$f2" = "" ]
              fi
            # ==================================================
            # Выбирается 1-я строка из этого файла
            s2=`head -n1 $f2`
            # ==================================================
            # Строка сравнивается с запомненной ранее строкой из 1-го
            # файла в списке
            if [ "$s1" = "$s2" ]; then
              # ================================================
              # Проверка - были ли уже совпадения
              if [ "$n" = "no" ]; then
                # ==============================================
                # Если совпадений не было - выводится имя 1-го файла из списка
                echo -n "$f1 "; n="yes"
                # ==============================================
                # Конец условия if [ "$n" = "no" ]
                fi
              # ================================================
              # Выводится имя файла, в котором найдено совпадение
              echo -n "$f2 "
              # ================================================
              # Файла, в котором найдено совпадение, удаляется из файла-списка
              sed ''$m'd' $HOME/temp01 > $HOME/temp02
              cat $HOME/temp02 >$HOME/temp01
              # ================================================
              # Конец действий при совпадении 
            else 
              # ================================================
              # Если нет совпадения - переход к следующему файлу из списка
              m=`expr $m + 1`
              # ================================================
              # Конец действий при отсутствии совпадения
              fi
            # ==================================================
            # Конец цикла перебора остальных файлов списка
            done
          # ====================================================
          # Если были найдены совпадения - выводится текст общей строки
          if [ "$n" = "yes" ]; then
            echo "- $s1"
            fi
          # ====================================================
          # Удаление 1-й строки из списка имен файлов
          sed '1d' $HOME/temp01 > $HOME/temp02
          cat $HOME/temp02 >$HOME/temp01
          # ====================================================
          # Конец цикла перебора имен файлов
          done
        # ======================================================
        # Переход к следующему параметру
        shift
        # ======================================================
        # Конец списка перебора параметров
        done
      # ========================================================
      # Удаление временного файла
      rm $HOME/temp*
      # ========================================================
      # Возврат в исходный каталог
      cd "$mydir"
      # ======== Конец скрипта ex7_2 ================================= #

Образец выполнения созданной команды:


bash2-2.05$ ex7_2 ../ap10999 /home/metod
Каталог ../ap10999 недоступен/не существует
Каталог: /home/metod
Hum-Dum.txt H1 - Humpty-Dumpty
nikOl_01 nikOl_02 nikOl_03 nikOl_04 nikOl_05 nikOl_06 nikOl_07 nikOl_08 nikOl_09
 nikOl_10 nikOl_11 nikOl_12 nikOl_13 nikOl_14 nikOl_15 nikOl_16 nikOl_17 nikOl_1
8 - Николай Олейников
bash2-2.05$


 

Пример 3

Задание
По информации файлов /home/metod/query* для заданного кода товара определить, сколько его экземпляров было продано в заданный месяц.

Формат применения:

   команда месяц код_товара...

Месяц задается в формате: MON-YY, например: JAN-90, JUN-89, NOV-17 и т.п.

Cкрипт назван ex7_3, его текст с подробными комментариями приводится ниже.

     #!/bin/bash2
     # ============================================================== #
     # Скрипт ex7_3: выборка объема продаж заданного товара           #
     # ============================================================== #
     # Выбирается 1-й параметр и список параметров сдвигается
     mon=$1; shift
     # =======================================================
     # Месяц записывается в файл
     echo "$mon" >$HOME/temp01
     # =======================================================
     # Остальные параметры команды представляют собой список кодов товаров.
     # Цикл, который выполняется до тех пор, пока остаются
     # необработанные параметры.
     while [ $# -ne 0 ]
      do
      # =====================================================
      # Код товара запоминается в переменной и записывается в файл
      code=$1
      echo "$code" >$HOME/temp02
      # =====================================================
      #  КОНВЕЙЕР 1
      # =====================================================
      # В файле query5 удаляются лишние пробелы
      sed -n 's/  */ /gp' /home/metod/query5 |
      # =====================================================
      # Выбираются столбцы: код заказа, код товара, количество
      cut -f2,3,5 -d' ' |
      # =====================================================
      # Сортировка по коду товара
      sort +1 -2 -t' ' | 
      # =====================================================
      # Соединение с файлом - кодом товара
      join -j1 2 -j2 1 -t' ' - $HOME/temp02 |
      # =====================================================
      # Выбираются столбцы: код заказа, количество
      # (код товара больше не нужен)
      cut -f2,3 -d' ' |
      # =====================================================
      # Сортировка по коду заказа и сохранение в файле
      sort +0 -1 -t' ' >$HOME/temp03 
      #
      # =====================================================
      #  КОНВЕЙЕР 2
      # =====================================================
      # В файле query4 удаляются лишние пробелы
      sed -n 's/  */ /gp' /home/metod/query4 |
      # =====================================================
      # Выбираются столбцы: код заказа, дата
      cut -f1,4 -d' ' |
      # =====================================================
      # Сортировка по коду заказа
      sort +0 -1 -t' ' |
      # =====================================================
      # Соединение с файлом - месяцем
      sed -n '/'$mon'/p' |
      # =====================================================
      # Выбирается столбец кода заказа
      # (дата больше не нужна)
      cut -f1 -d' ' |
      # =====================================================
      # Сортировка по коду 
      sort +0 -1 -t' ' |
      # =====================================================
      # Соединение с файлом заказов по заданному товару 
      join -j1 1 -j2 1 - $HOME/temp03 |
      # =====================================================
      # Выбирается столбец количества
      cut -f2 -d' ' >$HOME/temp01
      # =====================================================
      # Начальное значение суммы - 0
      sum=0
      # =====================================================
      # Содержимое файла temp01 составляеn список цикла for
      for value in `cat $HOME/temp01`
        do
        # ===================================================
        # Суммирование элементов списка
        sum=`expr "$sum" + "$value"`    
        done
      # =====================================================
      # Вывод результата
      echo "Продано товара $code в $mon - $sum шт."
      # =====================================================
      # Сдвиг списка параметров
      shift
      # =====================================================
      # Конец цикла перебора параметрjв
      done
    # =======================================================
    # После выхода из цикла - удаление временных файлов
    rm $HOME/temp01
    rm $HOME/temp02
    rm $HOME/temp03
    # ======== Конец скрипта ex7_3 ================================= #

Образец выполнения созданной команды:


bash2-2.05$ sh sss JAN-91 100860 100861 100862
Продано товара 100860 в JAN-91 - 100 шт.
Продано товара 100861 в JAN-91 - 20 шт.
Продано товара 100862 в JAN-91 - 0 шт.
bash2-2.05$


Назад