Site Loader

Содержание

как написать JavaScript — руководства на Skillbox


Если бы для интернета писали Библию, она начиналась бы так:

Сначала была почта. И увидели инженеры, что это хорошо. И создали они WWW с гиперссылками. И увидели инженеры, что это тоже хорошо. И создали они тогда язык JavaScript для оживления страничек.

Примерно так происходило в реальности. JavaScript придумали, чтобы «оживить» HTML. Скрипты JavaScript пишутся непосредственно в текст HTML или хранятся в отдельных файлах, как и стили CSS. Они выполняются сразу после загрузки страницы в браузер.

Даже сам язык в первое время назывался LiveScript. Потом его переименовали в JavaScript, потому что планировали как-то увязать с языком общего назначения Java. Но сейчас у них нет практически ничего общего, а JavaScript — совершенно независимый язык программирования со своей четкой спецификацией ECMAScript.

Формально JavaScript является торговой маркой Oracle, а этот язык — «расширение» ECMAScript, наряду с JScript от Microsoft и ActionScript, но это скорее заморочки владельцев торговых марок. Главное, что свободный ECMAScript никому не принадлежит.


Со временем сфера влияния JavaScript значительно расширилась. Его начали использовать не только для скриптов на странице HTML, но и для серьезных больших веб-приложений и целых программ, которые работают в браузере. Есть инструменты, чтобы специальным образом «упаковать» эти программы и выполнять их отдельно от браузера. Это компиляторы и интерпретаторы, которые более подробно рассматриваются на обучающих курсах «Java-разработчик» и «Веб-разработчик».

Приложения JavaScript выполняются в любой среде, где есть соответствующий интерпретатор.

Нас пока интересуют только браузеры и HTML-странички.

Как сделать JavaScript? Написать элементарный скрипт не сложнее, чем простую HTML-страничку, ведь скрипты JavaScript пишутся обычным текстом, то есть их можно создавать буквально в том же «Блокноте», сохраняя потом в отдельных файлах или вставляя в тело HTML-документа. Самые простые вещи на JavaScript делаются действительно просто.

Для примера сделаем простой скрипт для выполнения сервером сценариев Windows. Этот скрипт можно написать прямо в «Блокноте» и выполнить без браузера.

WScript.echo ("Привет, Skillbox!")

Пишем этот текст в «Блокноте», затем сохраняем файл под именем skillbox.js и запускаем в «Проводнике» Windows.

Аналогичный скрипт можно записать прямо в коде страницы HTML между тегами <script> и </script>. Там уже можно использовать обычные методы JavaScript, а не метод echo специфического объекта WScript. Рассмотрим некоторые из стандартных методов для ввода и вывода данных в браузере.

Метод alert() отображает окошко с кнопкой «OK». В окне выводится сообщение, которое указано в скобках. Например, «Привет, Skillbox!». То есть в данном случае браузер делает ровно то же самое, что перед этим делал сервер сценариев Windows.

Эти примеры тоже можно писать в «Блокноте», только сохранять в файлах с расширением


HTML. Например, skillbox.htm.

<html>
   <script>
      alert("Привет, Skillbox")
   </script>
</html>

Результат:

В качестве аргумента alert() можно указать не только конкретный текст, но и результат каких-либо вычислений или обработки других данных. Например, alert(x), где x вычисляется отдельно.

Метод confirm() выводит такое же окно с сообщением, но уже с двумя кнопками — «ОК» и «Отмена». В зависимости от того, какую кнопку щелкнет пользователь, метод возвращает либо значение true, либо false. Сервер получает это возвращаемое значение от пользователя и выполняет какое-то действие, в зависимости от ответа.

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

<html

>
   <script>
      confirm("Привет, Skillbox")
   </script>
</html>

Результат:

Метод prompt() выводит диалоговое окно с сообщением и текстовым полем, куда пользователь вводит данные. Здесь тоже предусмотрены две кнопки «ОК» и «Отмена». По нажатию первой кнопки метод возвращает на сервер введенный текст, а по нажатию второй кнопки возвращает логическое значение false.

Синтаксис здесь такой:

prompt (сообщение, значение_поля_ввода_данных)

Значение поля ввода необязательно. Туда можно вписать текст, который изначально введен в поле для удобства пользователя.

Код:

<html>
   <script>
      prompt("Передай привет Skillbox", "Привет")
   </script>
</html>



Результат:

Возможности современного JavaScript выходят далеко за рамки примитивного ввода-вывода данных через формы. Эти методы мы привели только в качестве самых простых примеров. Кроме этого, JavaScript позволяет реагировать на действия пользователя. Например, на движения мышкой или нажатие определенных клавиш. JavaScript часто используется для обеспечения асинхронной работы (Технология AJAX), когда информация на странице обновляется без ее перезагрузки. В этом режиме данные отправляются на сервер и загружаются оттуда в интерактивном режиме. Кроме того, JavaScript способен манипулировать с HTML-элементами на странице (создавать и прятать теги и т.д.) и делать многое другое.

Во всех популярных браузерах есть специальная консоль разработчика. Она показывает код скриптов на странице, а также выводит другую полезную информацию. В Chrome, Firefox и IE консоль разработчика открывается по нажатию горячей клавиши F12, в Safari — Ctrl+Shift+I

или Ctrl+Alt+C. На скриншоте скрипты отображаются справа вверху, вместе с другими элементами веб-страницы.


Консоль разработчика в Chrome.

В дальнейшем для удобного программирования понадобится установить редактор кода или IDE (Integrated Development Environment), интегрированную среду разработки. IDE — это редактор с расширенной функциональностью, который интегрирован с другими полезными инструментами, поддерживает подключение дополнительных модулей и так далее.

Для начала можно рекомендовать один из легких редакторов:

В будущем есть смысл присмотреться к IDE:

Инструкторы на курсе «JavaScript с нуля» посоветуют лучшие инструменты и помогут разобраться с любыми вопросами. Это практический 4-месячный курс для тех, кто хочет научиться основам языка сценариев с индивидуальным наставником, разработать фронтенд для интерактивного веб-проекта и положить кейс к себе в портфолио.

Курс идеально подойдет дизайнерам-разработчикам и начинающим программистам, кто уже знаком и умеет разрабатывать страницу на 



HTML и CSS, но не намерен останавливаться в изучении программирования. Преподаватели практически «на пальцах» объяснят базовые основы синтаксиса JavaScript, научат создавать визуальные интерактивные элементы и помогут разработать первый веб-проект на JavaScript.

Курс «JavaScript с нуля»

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

  • Живая обратная связь с преподавателями
  • Неограниченный доступ к материалам курса
  • Стажировка в компаниях-партнёрах
  • Дипломный проект от реального заказчика
  • Гарантия трудоустройства в компании-партнёры для выпускников, защитивших дипломные работы

Приемы написания скриптов в Bash / Habr


Администраторам Linux писать скрипты на Bash приходится регулярно. Ниже я привожу советы, как можно ускорить эту работу, а также повысить надежность скриптов.

Совет 1

Не пишите скриптов, которые выполняют действия ничего не спрашивая. Такие скрипты нужны довольно редко. А вот всевозможного «добра» для копирования, синхронизации, запуска чего-либо, хоть отбавляй. И если в любимом Midnight Commander Вы вдруг нажали не на тот скрипт, то с системой может произойти все что угодно. Это как правила дорожного движения — «написано кровью».

Совет 2

Отталкиваясь от предыдущего, в начало каждого скрипта неплохо помещать что-то вроде:

read -n 1 -p "Ты уверен, что хочешь запустить это (y/[a]): " AMSURE 
[ "$AMSURE" = "y" ] || exit
echo "" 1>&2

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

Совет 3

Это ключевой совет из всех. Для того, чтобы не писать каждый раз одно и то же — пользуйтесь библиотеками функций. Прочитав много статей по Bash, я вынужден констатировать, что этой теме уделяется мало внимания. Возможно в силу очевидности. Однако я считаю необходимым напомнить об этом. Итак.



Заведите свою библиотеку функций, например myfunc.sh и положите ее, например в /usr/bin. При написании скриптов она не только поможет сократить ваш труд, но и позволит одним махом доработать множество скриптов, если Вы улучшите какую-либо функцию.
Например, в свете совета 2 можно написать такую функцию:

myAskYN() 
{
local AMSURE
if [ -n "$1" ] ; then
   read -n 1 -p "$1 (y/[a]): " AMSURE
else
   read -n 1 AMSURE
fi
echo "" 1>&2
if [ "$AMSURE" = "y" ] ; then
   return 0
else
   return 1
fi
}

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

myAskYN "Ты уверен, что хочешь запустить это?" || exit

Можно написать и еще одну аналогичную функцию myAskYNE, с буквой E на конце, в которой return заменить на exit. Тогда запись будет еще проще:

myAskYNE "Ты уверен, что хочешь запустить это?"

Плюсы очевидны: а) пишете меньше кода, б) код легче читать, в) не отвлекаетесь на мелочи, вроде приставки " (y/[a]): " к тесту (замечу, что [a] означает any, а забранная в квадратные кавычки указывает, что это по умолчанию).

И последнее здесь. Для того, чтобы использовать функции из нашей библиотеки, ее надо не забыть включить в сам скрипт:

#!/bin/bash 
a1=myfunc.sh ; source "$a1" ; if [ $? -ne 0 ] ; then echo "Ошибка —
нет библиотеки функций $a1" 1>&2 ; exit 1 ; fi 

myAskYN "Ты уверен, что хочешь запустить это?" 
echo Run!

Я намеренно уложил весь вызов и обработку ошибки в одну строку, поскольку это вещь стандартная и не относится напрямую к логике скрипта. Зачем же ее растягивать на пол-экрана? Обратите также внимание, что имя скрипта присваивается переменной. Это позволяет задавать имя скрипта один раз, а стало быть, можно дублировать строку и заменить имя библиотеки, чтобы подключить другую библиотеку функций, если надо.
Теперь любой скрипт, начинающийся с этих трех строчек никогда не выполнит что-то без подтверждения. Предоставляю вам самим написать аналогичную myAskYN функцию, называемую myAskYESNO.

Совет 4

Разовьем успех и продемонстрируем несколько очевидных функций с минимальными комментариями.

sayWait() 
{ 
   local AMSURE 
   [ -n "$1" ] && echo "[email protected]" 1>&2 
   read -n 1 -p "(нажмите любую клавишу для продолжения)" AMSURE 
   echo "" 1>&2 
} 
 
 cdAndCheck() 
{ 
   cd "$1" 
   if ! [ "$(pwd)" = "$1" ] ; then 
      echo "!!Не могу встать в директорию $1 - продолжение невозможно. Выходим." 1>&2 
      exit 1 
   fi 
} 
 
 checkDir() 
{ 
   if ! [ -d "$1" ] ; then 
      if [ -z "$2" ] ; then 
         echo "!!Нет директории $1 - продолжение невозможно. Выходим." 1>&2 
      else 
         echo "$2" 1>&2 
      fi 
      exit 1 
   fi 
} 
checkFile() 
{ 
   if ! [ -f "$1" ] ; then 
      if [ -z "$2" ] ; then 
         echo "!!Нет файла $1 - продолжение невозможно. Выходим." 1>&2 
      else 
         echo "$2" 1>&2 
      fi 
      exit 1 
   fi 
} 
checkParm() 
{ 
   if [ -z "$1" ] ; then 
      echo "!!$2. Продолжение невозможно.  Выходим." 1>&2 
      exit 1 
   fi 
}

Здесь обращу ваше внимание на постоянно встречающееся сочетание 1>&2 после echo. Дело в том, что ваши скрипты, возможно, будут выводить некую ценную информацию. И не всегда эта информация влезет в экран, а потому ее неплохо бывает сохранить в файл или отправить на less. Комбинация 1>&2 означает перенаправление вывода на стандартное устройство ошибок. И когда вы вызываете скрипт таким образом:

my-script.sh > out.txt
my-script.sh | less

в нем не окажется лишних ошибочных и служебных сообщений, а только то, что вы действительно хотите вывести.

Совет 5

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

curPath=  # переменная с текущим абсолютным путем, где находится скрипт
cRes=     # переменная для возврата текстовых значений из функций
pYes=     # параметр --yes, который обсудим позднее

Теперь можем добавить к коллекции еще такую полезную функцию:

input1() 
{ 
   local a1 
 
   if [ -n "$1" ] ; then 
      read -p "$1" -sn 1 cRes 
   else 
      read -sn 1 cRes 
   fi 
 
   # Проверка допустимых выборов 
   while [ "$2" = "${2#*$cRes}" ] ; do 
      read -sn 1 cRes 
   done 
   echo $cRes 1>&2 
}

Вот пример ее использования:

cat <<'EOF' 
Выбери желаемое действие: 
------------------------ 
   a) Действие 1 
   b) Действие 2 
   .) Выход 
EOF 
input1 "Твой выбор: " "ab." 
echo "Выбор был: $cRes"

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

Совет 6

Какой скрипт без параметров? Об их обработке написано тонны литературы. Поделюсь своим видением.

  1. Крайне желательно, чтобы параметры обрабатывались независимо от их последовательности.
  2. Я не люблю использовать однобуквенные параметры (а следовательно и getopts) по той простой причине, что скриптов очень много, а букв мало. И запомнить, что для одного скрипта -r означает replace, для другого replicate, а для третьего вообще remove практически невозможно. Поэтому я использую 2 нотации, причем одновременно: а) --show-files-only, б) -sfo (как сокращение от предыдущего). Практика показывает, что такие ключи запоминаются мгновенно и очень надолго.
  3. Скрипт должен выдавать ошибку на неизвестный ему ключ. Это частично поможет выявить ошибки при написании параметров.
  4. Из совета 2 возьмем правило: никогда не запускать скрипт без подтверждения. Но добавим к этому важное исключение — если не указан ключ --yes (ключ, конечно, может быть любым).
  5. Ключи могут сопровождаться значением. В этом случае для длинных ключей действует такое правило: --source-file=my.txt (написание через равно), а для коротких такое: -sf my.txt (через пробел).

В этом свете обработка параметров может выглядеть так:

while [ 1 ] ; do 
   if [ "$1" = "--yes" ] ; then 
      pYes=1 
   elif [ "${1#--source-file=}" != "$1" ] ; then 
      pSourceFile="${1#--source-file=}" 
   elif [ "$1" = "-sf" ] ; then 
      shift ; pSourceFile="$1" 
   elif [ "${1#--dest-file=}" != "$1" ] ; then 
      pDestFile="${1#--dest-file=}" 
   elif [ "$1" = "-df" ] ; then 
      shift ; pDestFile="$1" 
   elif [ -z "$1" ] ; then 
      break # Ключи кончились 
   else 
      echo "Ошибка: неизвестный ключ" 1>&2 
      exit 1 
   fi 
   shift 
done 
 
checkParm "$pSourceFile" "Не задан исходный файл" 
checkParm "$pDestFile" "Не задан выходной файл" 
 
if [ "$pYes" != "1" ] ; then 
   myAskYNE "Ты уверен, что хочешь запустить это?" 
fi 
echo "source=$pSourceFile, destination=$pDestFile"

Этот код дает следующие возможности:Это базовая часть, которую можно развивать и дальше. Например, добавим пару функций обработки параметров в нашу библиотеку:

procParmS() 
{ 
   [ -z "$2" ] && return 1 
   if [ "$1" = "$2" ] ; then 
      cRes="$3" 
      return 0 
   fi 
   return 1 
} 
procParmL() 
{ 
   [ -z "$1" ] && return 1 
   if [ "${2#$1=}" != "$2" ] ; then 
      cRes="${2#$1=}" 
      return 0 
   fi 
   return 1 
} 

При этом цикл обработки параметров будет выглядеть гораздо более удобоваримым:

while [ 1 ] ; do 
   if [ "$1" = "--yes" ] ; then 
      pYes=1 
   elif procParmS "-sf" "$1" "$2" ; then 
      pSourceFile="$cRes" ; shift 
   elif procParmL "--source-file" "$1" ; then 
      pSourceFile="$cRes" 
   elif procParmS "-df" "$1" "$2" ; then 
      pDestFile="$cRes" ; shift 
   elif procParmL "--dest-file" "$1" ; then 
      pDestFile="$cRes" 
   elif [ -z "$1" ] ; then 
      break # Ключи кончились 
   else 
      echo "Ошибка: неизвестный ключ" 1>&2 
      exit 1 
   fi 
   shift 
done

Фактически, этот цикл можно копировать из скрипта в скрипт не задумываясь ни о чем, кроме названий ключей и имени переменной для этого ключа. Причем они в данном случае не повторяются и возможность ошибки исключена.
Нет предела совершенству, и можно еще долго «улучшать» функции, например в procParmS проверить на непустое значение третий параметр и вывалиться по ошибке в таком случае. И так далее.
Файл библиотеки функций из этого примера можно скачать здесь.
Тестовый файл здесь.

начало / RUVDS.com corporate blog / Habr


Bash-скрипты: начало
Bash-скрипты, часть 2: циклы
Bash-скрипты, часть 3: параметры и ключи командной строки
Bash-скрипты, часть 4: ввод и вывод
Bash-скрипты, часть 5: сигналы, фоновые задачи, управление сценариями
Bash-скрипты, часть 6: функции и разработка библиотек
Bash-скрипты, часть 7: sed и обработка текстов
Bash-скрипты, часть 8: язык обработки данных awk
Bash-скрипты, часть 9: регулярные выражения
Bash-скрипты, часть 10: практические примеры
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит

Сегодня поговорим о bash-скриптах. Это — сценарии командной строки, написанные для оболочки bash. Существуют и другие оболочки, например — zsh, tcsh, ksh, но мы сосредоточимся на bash. Этот материал предназначен для всех желающих, единственное условие — умение работать в командной строке Linux.


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

Итак, если говорить о командной строке, она позволяет выполнить несколько команд за один раз, введя их через точку с запятой:

pwd ; whoami

На самом деле, если вы опробовали это в своём терминале, ваш первый bash-скрипт, в котором задействованы две команды, уже написан. Работает он так. Сначала команда pwd выводит на экран сведения о текущей рабочей директории, потом команда whoamiпоказывает данные о пользователе, под которым вы вошли в систему.

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

getconf ARG_MAX

Командная строка — отличный инструмент, но команды в неё приходится вводить каждый раз, когда в них возникает необходимость. Что если записать набор команд в файл и просто вызывать этот файл для их выполнения? Собственно говоря, тот файл, о котором мы говорим, и называется сценарием командной строки.

Как устроены bash-скрипты

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

#!/bin/bash

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

Команды оболочки отделяются знаком перевода строки, комментарии выделяют знаком решётки. Вот как это выглядит:

#!/bin/bash
# This is a comment
pwd
whoami

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

Установка разрешений для файла сценария

Сохраните файл, дав ему имя myscript, и работа по созданию bash-скрипта почти закончена. Сейчас осталось лишь сделать этот файл исполняемым, иначе, попытавшись его запустить, вы столкнётесь с ошибкой Permission denied.
Попытка запуска файла сценария с неправильно настроенными разрешениями

Сделаем файл исполняемым:

chmod +x ./myscript

Теперь попытаемся его выполнить:

./myscript

После настройки разрешений всё работает как надо.
Успешный запуск bash-скрипта

Вывод сообщений

Для вывода текста в консоль Linux применяется команда echo. Воспользуемся знанием этого факта и отредактируем наш скрипт, добавив пояснения к данным, которые выводят уже имеющиеся в нём команды:

#!/bin/bash
# our comment is here
echo "The current directory is:"
pwd
echo "The user logged in is:"
whoami

Вот что получится после запуска обновлённого скрипта.
Вывод сообщений из скрипта

Теперь мы можем выводить поясняющие надписи, используя команду echo. Если вы не знаете, как отредактировать файл, пользуясь средствами Linux, или раньше не встречались с командой echo, взгляните на этот материал.

Использование переменных

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

Нет ничего плохого в исполнении отдельных команд без хранения результатов их работы, но возможности такого подхода весьма ограничены.

Существуют два типа переменных, которые можно использовать в bash-скриптах:

  • Переменные среды
  • Пользовательские переменные

Переменные среды

Иногда в командах оболочки нужно работать с некими системными данными. Вот, например, как вывести домашнюю директорию текущего пользователя:

#!/bin/bash
# display user home
echo "Home for the current user is: $HOME"

Обратите внимание на то, что мы можем использовать системную переменную $HOME в двойных кавычках, это не помешает системе её распознать. Вот что получится, если выполнить вышеприведённый сценарий.
Использование переменной среды в сценарии

А что если надо вывести на экран значок доллара? Попробуем так:

echo "I have $1 in my pocket"

Система обнаружит знак доллара в строке, ограниченной кавычками, и решит, что мы сослались на переменную. Скрипт попытается вывести на экран значение неопределённой переменной $1. Это не то, что нам нужно. Что делать?

В подобной ситуации поможет использование управляющего символа, обратной косой черты, перед знаком доллара:

echo "I have \$1 in my pocket"

Теперь сценарий выведет именно то, что ожидается.
Использование управляющей последовательности для вывода знака доллара

Пользовательские переменные

В дополнение к переменным среды, bash-скрипты позволяют задавать и использовать в сценарии собственные переменные. Подобные переменные хранят значение до тех пор, пока не завершится выполнение сценария.

Как и в случае с системными переменными, к пользовательским переменным можно обращаться, используя знак доллара:
TNW-CUS-FMP — промо-код на 10% скидку на наши услуги, доступен для активации в течение 7 дней

#!/bin/bash
# testing variables
grade=5
person="Adam"
echo "$person is a good boy, he is in grade $grade"

Вот что получится после запуска такого сценария.
Пользовательские переменные в сценарии

Подстановка команд

Одна из самых полезных возможностей bash-скриптов — это возможность извлекать информацию из вывода команд и назначать её переменным, что позволяет использовать эту информацию где угодно в файле сценария.

Сделать это можно двумя способами.

  • С помощью значка обратного апострофа «`»
  • С помощью конструкции $()

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

mydir=`pwd`

При втором подходе то же самое записывают так:

mydir=$(pwd)

А скрипт, в итоге, может выглядеть так:

#!/bin/bash
mydir=$(pwd)
echo $mydir

В ходе его работы вывод команды pwdбудет сохранён в переменной mydir, содержимое которой, с помощью команды echo, попадёт в консоль.
Скрипт, сохраняющий результаты работы команды в переменной

Математические операции

Для выполнения математических операций в файле скрипта можно использовать конструкцию вида $((a+b)):

#!/bin/bash
var1=$(( 5 + 5 ))
echo $var1
var2=$(( $var1 * 2 ))
echo $var2

Математические операции в сценарии

Управляющая конструкция if-then

В некоторых сценариях требуется управлять потоком исполнения команд. Например, если некое значение больше пяти, нужно выполнить одно действие, в противном случае — другое. Подобное применимо в очень многих ситуациях, и здесь нам поможет управляющая конструкция if-then. В наиболее простом виде она выглядит так:

if команда
then
команды
fi

А вот рабочий пример:

#!/bin/bash
if pwd
then
echo "It works"
fi

В данном случае, если выполнение команды pwdзавершится успешно, в консоль будет выведен текст «it works».

Воспользуемся имеющимися у нас знаниями и напишем более сложный сценарий. Скажем, надо найти некоего пользователя в /etc/passwd, и если найти его удалось, сообщить о том, что он существует.

#!/bin/bash
user=likegeeks
if grep $user /etc/passwd
then
echo "The user $user Exists"
fi

Вот что получается после запуска этого скрипта.
Поиск пользователя

Здесь мы воспользовались командой grepдля поиска пользователя в файле /etc/passwd. Если команда grepвам незнакома, её описание можно найти здесь.

В этом примере, если пользователь найден, скрипт выведет соответствующее сообщение. А если найти пользователя не удалось? В данном случае скрипт просто завершит выполнение, ничего нам не сообщив. Хотелось бы, чтобы он сказал нам и об этом, поэтому усовершенствуем код.

Управляющая конструкция if-then-else

Для того, чтобы программа смогла сообщить и о результатах успешного поиска, и о неудаче, воспользуемся конструкцией if-then-else. Вот как она устроена:

if команда
then
команды
else
команды
fi

Если первая команда возвратит ноль, что означает её успешное выполнение, условие окажется истинным и выполнение не пойдёт по ветке else. В противном случае, если будет возвращено что-то, отличающееся от нуля, что будет означать неудачу, или ложный результат, будут выполнены команды, расположенные после else.

Напишем такой скрипт:

#!/bin/bash
user=anotherUser
if grep $user /etc/passwd
then
echo "The user $user Exists"
else
echo "The user $user doesn’t exist"
fi

Его исполнение пошло по ветке else.
Запуск скрипта с конструкцией if-then-else

Ну что же, продолжаем двигаться дальше и зададимся вопросом о более сложных условиях. Что если надо проверить не одно условие, а несколько? Например, если нужный пользователь найден, надо вывести одно сообщение, если выполняется ещё какое-то условие — ещё одно сообщение, и так далее. В подобной ситуации нам помогут вложенные условия. Выглядит это так:

if команда1
then
команды
elif команда2
then
команды
fi

Если первая команда вернёт ноль, что говорит о её успешном выполнении, выполнятся команды в первом блоке then, иначе, если первое условие окажется ложным, и если вторая команда вернёт ноль, выполнится второй блок кода.

#!/bin/bash
user=anotherUser
if grep $user /etc/passwd
then
echo "The user $user Exists"
elif ls /home
then
echo "The user doesn’t exist but anyway there is a directory under /home"
fi

В подобном скрипте можно, например, создавать нового пользователя с помощью команды useradd, если поиск не дал результатов, или делать ещё что-нибудь полезное.

Сравнение чисел

В скриптах можно сравнивать числовые значения. Ниже приведён список соответствующих команд.

n1 -eq n2Возвращает истинное значение, если n1 равно n2.
n1 -ge n2 Возвращает истинное значение, если n1больше или равно n2.
n1 -gt n2Возвращает истинное значение, если n1 больше n2.
n1 -le n2Возвращает истинное значение, если n1меньше или равно n2.
n1 -lt n2Возвращает истинное значение, если n1 меньше n2.
n1 -ne n2Возвращает истинное значение, если n1не равно n2.

В качестве примера опробуем один из операторов сравнения. Обратите внимание на то, что выражение заключено в квадратные скобки.

#!/bin/bash
val1=6
if [ $val1 -gt 5 ]
then
echo "The test value $val1 is greater than 5"
else
echo "The test value $val1 is not greater than 5"
fi

Вот что выведет эта команда.
Сравнение чисел в скриптах

Значение переменной val1больше чем 5, в итоге выполняется ветвь thenоператора сравнения и в консоль выводится соответствующее сообщение.

Сравнение строк

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

str1 = str2 Проверяет строки на равенство, возвращает истину, если строки идентичны.

str1 != str2Возвращает истину, если строки не идентичны.
str1 < str2Возвращает истину, если str1меньше, чем str2.
str1 > str2 Возвращает истину, если str1больше, чем str2.
-n str1 Возвращает истину, если длина str1больше нуля.
-z str1Возвращает истину, если длина str1равна нулю.

Вот пример сравнения строк в сценарии:

#!/bin/bash
user ="likegeeks"
if [$user = $USER]
then
echo "The user $user  is the current logged in user"
fi

В результате выполнения скрипта получим следующее.
Сравнение строк в скриптах

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

Вот как работа с этими операторами выглядит в коде:

#!/bin/bash
val1=text
val2="another text"
if [ $val1 \> $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi

Вот результаты работы скрипта.
Сравнение строк, выведенное предупреждение

Обратите внимание на то, что скрипт, хотя и выполняется, выдаёт предупреждение:

./myscript: line 5: [: too many arguments

Для того, чтобы избавиться от этого предупреждения, заключим $val2 в двойные кавычки:

#!/bin/bash
val1=text
val2="another text"
if [ $val1 \> "$val2" ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi

Теперь всё работает как надо.
Сравнение строк

Ещё одна особенность операторов «>» и «<» заключается в том, как они работают с символами в верхнем и нижнем регистрах. Для того, чтобы понять эту особенность, подготовим текстовый файл с таким содержимым:

Likegeeks
likegeeks

Сохраним его, дав имя myfile, после чего выполним в терминале такую команду:

sort myfile

Она отсортирует строки из файла так:

likegeeks
Likegeeks

Команда sort, по умолчанию, сортирует строки по возрастанию, то есть строчная буква в нашем примере меньше прописной. Теперь подготовим скрипт, который будет сравнивать те же строки:

#!/bin/bash
val1=Likegeeks
val2=likegeeks
if [ $val1 \> $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi

Если его запустить, окажется, что всё наоборот — строчная буква теперь больше прописной.
Команда sort и сравнение строк в файле сценария

В командах сравнения прописные буквы меньше строчных. Сравнение строк здесь выполняется путём сравнения ASCII-кодов символов, порядок сортировки, таким образом, зависит от кодов символов.

Команда sort, в свою очередь, использует порядок сортировки, заданный в настройках системного языка.

Проверки файлов

Пожалуй, нижеприведённые команды используются в bash-скриптах чаще всего. Они позволяют проверять различные условия, касающиеся файлов. Вот список этих команд.

-d fileПроверяет, существует ли файл, и является ли он директорией.
-e fileПроверяет, существует ли файл.
-f file Проверяет, существует ли файл, и является ли он файлом.
-r fileПроверяет, существует ли файл, и доступен ли он для чтения.
-s file Проверяет, существует ли файл, и не является ли он пустым.
-w fileПроверяет, существует ли файл, и доступен ли он для записи.
-x fileПроверяет, существует ли файл, и является ли он исполняемым.
file1 -nt file2 Проверяет, новее ли file1, чем file2.
file1 -ot file2Проверяет, старше ли file1, чем file2.
-O file Проверяет, существует ли файл, и является ли его владельцем текущий пользователь.
-G fileПроверяет, существует ли файл, и соответствует ли его идентификатор группы идентификатору группы текущего пользователя.

Эти команды, как впрочем, и многие другие рассмотренные сегодня, несложно запомнить. Их имена, являясь сокращениями от различных слов, прямо указывают на выполняемые ими проверки.

Опробуем одну из команд на практике:

#!/bin/bash
mydir=/home/likegeeks
if [ -d $mydir ]
then
echo "The $mydir directory exists"
cd $ mydir
ls
else
echo "The $mydir directory does not exist"
fi

Этот скрипт, для существующей директории, выведет её содержимое.
Вывод содержимого директории

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

Итоги

Сегодня мы рассказали о том, как приступить к написанию bash-скриптов и рассмотрели некоторые базовые вещи. На самом деле, тема bash-программирования огромна. Эта статья является переводом первой части большой серии из 11 материалов. Если вы хотите продолжения прямо сейчас — вот список оригиналов этих материалов. Для удобства сюда включён и тот, перевод которого вы только что прочли.

  1. Bash Script Step By Step — здесь речь идёт о том, как начать создание bash-скриптов, рассмотрено использование переменных, описаны условные конструкции, вычисления, сравнения чисел, строк, выяснение сведений о файлах.
  2. Bash Scripting Part 2, Bash the awesome — тут раскрываются особенности работы с циклами for и while.
  3. Bash Scripting Part 3, Parameters & options — этот материал посвящён параметрам командной строки и ключам, которые можно передавать скриптам, работе с данными, которые вводит пользователь, и которые можно читать из файлов.
  4. Bash Scripting Part 4, Input & Output — здесь речь идёт о дескрипторах файлов и о работе с ними, о потоках ввода, вывода, ошибок, о перенаправлении вывода.
  5. Bash Scripting Part 5, Sighals & Jobs — этот материал посвящён сигналам Linux, их обработке в скриптах, запуску сценариев по расписанию.
  6. Bash Scripting Part 6, Functions — тут можно узнать о создании и использовании функций в скриптах, о разработке библиотек.
  7. Bash Scripting Part 7, Using sed — эта статья посвящена работе с потоковым текстовым редактором sed.
  8. Bash Scripting Part 8, Using awk — данный материал посвящён программированию на языке обработки данных awk.
  9. Bash Scripting Part 9, Regular Expressions — тут можно почитать об использовании регулярных выражений в bash-скриптах.
  10. Bash Scripting Part 10, Practical Examples — здесь приведены приёмы работы с сообщениями, которые можно отправлять пользователям, а так же методика мониторинга диска.
  11. Bash Scripting Part 11, Expect Command — этот материал посвящён средству Expect, с помощью которого можно автоматизировать взаимодействие с интерактивными утилитами. В частности, здесь идёт речь об expect-скриптах и об их взаимодействии с bash-скриптами и другими программами.

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

Уважаемые читатели! Просим гуру bash-программирования рассказать о том, как они добрались до вершин мастерства, поделиться секретами, а от тех, кто только что написал свой первый скрипт, ждём впечатлений.

Как написать скрипт: 9-ти шаговая схема создания скрипта с нуля - ПораРасти


08 Ноя Как написать скрипт: 9-ти шаговая схема создания скрипта с нуля

Опубликовано: 22:26
В категории: Холодные звонки и продажи по телефону
Опубликовал: admin

Как написать скрипт продаж? Таким вопросом задается, наверное, каждый, кто работает в продажах. И это неудивительно — ведь хороший скрипт продаж позволит Вам быстрее и легче привлекать клиентов, поможет менеджерам преодолевать возражения и отвечать на вопросы потенциальных покупателей. Плюсы от использования скрипта очевидны.

Но есть и обратная сторона.

Разработка скрипта продаж — занятие не простое. В статье «3 способа написать и оформить скрипт продаж» я уже делился с Вами своим мнением по поводу подготовки скрипта (электронный формат, бумажный формат).

Сегодня я хочу предложить Вам схему создания скрипта — 9 шаговый алгоритм написания скрипта с нуля (речь идет про написание скрипта холодного звонка. Для других видов звонков алгоритм будет аналогичным с небольшими корректировками). Когда я создаю скрипты продаж для корпоративных клиентов, я сам опираюсь на этот алгоритм.

Я подготовил алгоритм в формате PDF. Скачать его можно бесплатно, разблокировав доступ через (нажать на любую кнопку соцсетей).

[sociallocker id=»17542″]

[/sociallocker]

Более подробно каждый шаг я описал в этих видео:

Как написать скрипт продаж: шаг 1-5 (видео)

Давайте рассмотрим основные шаги при написании скрипта.

1. Начни с сегментации

Этот шаг (к сожалению, незнакомый большинству) позволяет на начальном этапе разделить базу наших потенциальных клиентов на более перспективных и интересных для нас и на менее интересных. На этом шаге важно определить критерии сегментации для своей ситуации. Например, если я продаю тренинги продаж, то для меня клиент с наличием отдела продаж в компании и необученными сотрудниками будет гораздо интереснее, чем клиент вообще без отдела продаж. Таким образом мы для себя выделяем категории клиентов А, B, C и далее по необходимости для Вашего бизнеса. Более подробно этот важный шаг я разбирал на онлайн-тренинг Скрипты продаж, которые выстреливают (здесь можно посмотреть отчет с тренинга), но думаю логика сегментации Вам понятна.

2. Определи целевое действие

На этом шаге важно спланировать для каждого сегмента клиентов те целевые действия, которые будут нам выгодны. Например, с клиентами категории А мы готовы встречаться на территории клиента (т.к. они наиболее перспективные, интересные для нас. Мы готовы инвестировать свое время в таких клиентов), а с клиентами категории С, к примеру, можно ограничиться подпиской на рассылку.

3. Определи ЛПР 

ЛПР — лицо, принимающее решение. Кто в Вашем случае определяет решение о работе с Вами? Часто менеджеры напролом пробиваются к руководителю, не понимая, что решение по их вопросу в компании, вероятно принимает другой человек. Это важный шаг, который напрямую влияет на наполнение нашего скрипта эффективными речевыми оборотами.

4. Наполни таргет-лист

Таргет-лист — это список компаний для привлечения. Я рекомендую иметь небольшой список тех, кому Вы хотите позвонить уже в процессе составления скрипта.

5. Продумай выход на ЛПР

Что Вы скажете секретарю, чтобы он Вас соединил с руководителем. Мне обычно достаточно 2-3 техники чтобы обойти почти любого секретаря. В курсе 10 звонков — 10 продаж я о таких техниках рассказываю.

6. Определи идеальную линию разговора с ЛПР

Представьте, что Ваш разговор проходит идеально гладко. Клиент не возражает. Подумайте, с чего Вы начнете беседу, как утеплите контакт, как будете аргументировать свою позицию. Я обычно выделяю 4 составляющих в этом блоке, о которых расскажу в другой статье (техника «ВУУЗ»).

7. Добавь ветвистость

Скрипт продаж подразумевает разные варианты поведения клиентов. Он может согласиться с Вами сразу (в таком случае сработает Ваша идеальная линия разговора), либо будет отказывать и возражать. На 7 шаге важно предусмотреть возможные отказы и отговорки клиента. Я обычно выделяю возражения универсальные (они могут появиться на любом узле скрипта) и узловые (они могут появиться только на определенном узле. Например, во время установления контакта). Преодолеть любые возражения Вам поможет курс Хакер возражений. Там есть все необходимые приемы для обработки любых возражений.

8. Автоматизируй скрипт

На этом шаге я рекомендую автоматизировать скрипт продаж. Вы можете использовать заготовки для автоматизации (например, я использовал экселевский шаблон в курсе Конструктор скриптов продаж), либо специальные сервисы для автоматизации скриптов (мне нравится СкриптДизайнер).

9. Улучшай!

Следите за конверсией каждого узла, скрипта в целом, пробуйте разные ответы на возражения и способы аргументации. И у Вас получится убойный скрипт продаж!

С уважением, Олег (дружить в ВК, инстаграм)

P.s. Более подробно технологию создания скриптов я разобрал на онлайн-тренинге (точнее — воркшопе) Скрипты продаж, которые выстреливают. Посмотрите подробности о том, как прошло мероприятие, какие выводы я сделал для себя в ходе общения с участниками. Возможно, и для Вас и Вашей ситуации это будет полезным.

Полезные ссылки:

Основы BASH. Часть 1 / Habr


Безусловно, все те кто общается с ОС Linux хоть раз да имели дело(во всяком случае слышали точно) с командной оболочкой BASH. Но BASH не только командная оболочка, это еще и превосходный скриптовый язык программирования.
Цель этой статьи — познакомить поближе юзеров с bash, рассказать про синтаксис, основные приемы и фишки языка, для того чтобы даже обычный пользователь смог быстренько написать простой скрипт для выполнения ежедневной(-недельной, -месячной) рутинной работы или, скажем, «на коленке» наваять скриптик для бэкапа директории.

Введение

BASH — Bourne-Again SHell (что может переводится как «перерожденный шел», или «Снова шел Борна(создатель sh)»), самый популярный командный интерпретатор в юниксоподобных системах, в особенности в GNU/Linux. Ниже приведу ряд встроенных команд, которые мы будем использовать для создания своих скриптов.

break выход из цикла for, while или until

continue выполнение следующей итерации цикла for, while или until

echo вывод аргументов, разделенных пробелами, на стандартное устройство вывода

exit выход из оболочки

export отмечает аргументы как переменные для передачи в дочерние процессы в среде

hash запоминает полные имена путей команд, указанных в качестве аргументов, чтобы не искать их при следующем обращении

kill посылает сигнал завершения процессу

pwd выводит текущий рабочий каталог

read читает строку из ввода оболочки и использует ее для присвоения значений указанным переменным.\

return заставляет функцию оболочки выйти с указанным значением

shift перемещает позиционные параметры налево

test вычисляет условное выражение

times выводит имя пользователя и системное время, использованное оболочкой и ее потомками

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

unset вызывает уничтожение переменных оболочки

wait ждет выхода из дочернего процесса и сообщает выходное состояние.


И конечно же кроме встроенных команд мы будем использовать целую кучу внешних, отдельных команд-программ, с которыми мы познакомимся уже в процессе

Что необходимо знать с самого начала

1. Любой bash-скрипт должен начинаться со строки:

#!/bin/bash

в этой строке после #! указывается путь к bash-интерпретатору, поэтому если он у вас установлен в другом месте(где, вы можете узнать набрав whereis bash) поменяйте её на ваш путь.

2. Коментарии начинаются с символа # (кроме первой строки).

3. В bash переменные не имеют типа(о них речь пойдет ниже)

Переменные и параметры скрипта

Приведу как пример небольшой пример, который мы разберем:

#!/bin/bash

#указываем где у нас хранится bash-интерпретатор

parametr1=$1 #присваиваем переменной parametr1 значение первого параметра скрипта

script_name=$0 #присваиваем переменной script_name значение имени скрипта

echo "Вы запустили скрипт с именем $script_name и параметром $parametr1" # команда echo выводит определенную строку, обращение к переменным осуществляется через $имя_переменной.

echo 'Вы запустили скрипт с именем $script_name и параметром $parametr1' # здесь мы видим другие кавычки, разница в том, что в одинарных кавычках не происходит подстановки переменных.

exit 0 #Выход с кодом 0 (удачное завершение работы скрипта)

Результат выполнения скрипта:

[email protected]:~$ ./test.sh qwerty

Вы запустили скрипт с именем ./test.sh и параметром qwerty

Вы запустили скрипт с именем $script_name и параметром $parametr1

После того как мы познакомились как использовать переменные и передавать скрипту параметры, время познакомиться с зарезервированными переменными:

$DIRSTACK - содержимое вершины стека каталогов

$EDITOR - текстовый редактор по умолчанию

$EUID - Эффективный UID. Если вы использовали программу su для выполнения команд от другого пользователя, то эта переменная содержит UID этого пользователя, в то время как...

$UID - ...содержит реальный идентификатор, который устанавливается только при логине.

$FUNCNAME - имя текущей функции в скрипте.

$GROUPS - массив групп к которым принадлежит текущий пользователь

$HOME - домашний каталог пользователя

$HOSTNAME - ваш hostname

$HOSTTYPE - архитектура машины.

$LC_CTYPE - внутренняя переменная, котороя определяет кодировку символов

$OLDPWD - прежний рабочий каталог

$OSTYPE - тип ОС

$PATH - путь поиска программ

$PPID - идентификатор родительского процесса

$SECONDS - время работы скрипта(в сек.)

$# - общее количество параметров переданных скрипту

$* - все аргументы переданыне скрипту(выводятся в строку)

[email protected] - тоже самое, что и предыдущий, но параметры выводятся в столбик

$! - PID последнего запущенного в фоне процесса

$$ - PID самого скрипта

Условия

Условные операторы, думаю, знакомы практически каждому, кто хоть раз пытался на чем-то писать программы. В bash условия пишутся след. образом (как обычно на примере):
#!/bin/bash
source=$1 #в переменную source засовываем первый параметр скрипта
dest=$2 #в переменную dest засовываем второй параметр скрипта

if [[ "$source" -eq "$dest" ]] # в ковычках указываем имена переменных для сравнения. -eq - логическое сравнение обозначающие "равны"

then # если они действительно равны, то

echo "Применик $dest и источник $source один и тот же файл!" #выводим сообщение об ошибке, т.к. $source и $dest у нас равны

exit 1 # выходим с ошибкой (1 - код ошибки)

else # если же они не равны

cp $source $dest # то выполняем команду cp: копируем источник в приемник

echo "Удачное копирование!"

fi #обозначаем окончание условия.

Результат выполнения скрипта:
[email protected]:~$ ./primer2.sh 1 1

Применик 1 и источник 1 один и тот же файл!

[email protected]:~$ ./primer2.sh 1 2

Удачное копирование!


Структура if-then-else используется следующим образом:

if <команда или набор команд возвращающих код возврата(0 или 1)>

then

<если выражение после if истино, то выполняется этот блок>

else

<если выражение после if ложно, тот этот>

В качестве команд возвращающих код возврата могут выступать структуры [[ , [ , test, (( )) или любая другая(или несколько) linux-команда.

test - используется для логического сравнения. после выражения, неоьбходима закрывающая скобка "]"

[ - синоним команды test

[[ - расширенная версия "[" (начиная с версии 2.02)(как в примере), внутри которой могут быть использованы || (или), & (и). Долна иметь закрывающуб скобку "]]"

(( )) - математическое сравнение.

для построения многоярусных условий вида:
if ...

then ....

else

if ....

then....

else ....


для краткости и читаемости кода, можно использовать структуру:
if ..

then ...

elif ...

then ...

elif ...

Условия. Множественный выбор

Если необходимо сравнивать какоую-то одну переменную с большим количеством параметров, то целесообразней использовать оператор case.
#!/bin/bash

echo "Выберите редатор для запуска:"

echo "1 Запуск программы nano"

echo "2 Запуск программы vi"

echo "3 Запуск программы emacs"

echo "4 Выход"

read doing #здесь мы читаем в переменную $doing со стандартного ввода

case $doing in

1)

/usr/bin/nano # если $doing содержит 1, то запустить nano

;;

2)

/usr/bin/vi # если $doing содержит 2, то запустить vi

;;

3)

/usr/bin/emacs # если $doing содержит 3, то запустить emacs

;;

4)

exit 0

;;

*) #если введено с клавиатуры то, что в case не описывается, выполнять следующее:

echo "Введено неправильное действие"

esac #окончание оператора case.


Результат работы:
[email protected]:~$ ./menu2.sh

Выберите редатор для запуска:

1 Запуск программы nano

2 Запуск программы vi

3 Запуск программы emacs

4 Выход

После выбор цифры и нажатия Enter запуститься тот редактор, который вы выбрали(если конечно все пути указаны правильно, и у вас установлены эти редакторы 🙂 )
Прведу список логических операторв, которые используются для конструкции if-then-else-fi:
-z # строка пуста

-n # строка не пуста

=, (==) # строки равны

!= # строки неравны

-eq # равно

-ne # неравно

-lt,(< ) # меньше

-le,(<=) # меньше или равно

-gt,(>) #больше

-ge,(>=) #больше или равно

! #отрицание логического выражения

-a,(&&) #логическое «И»

-o,(||) # логическое «ИЛИ»

С основами языка и условиями мы разобрались, чтобы не перегружать статью, разобью её на несколько частей(допустим на 3). Во второй части разберем операторы цикла и выполнение математических операций.

UPD: Исправил некоторые ошибки
UPD: Обновил часть про условия if-then-else

Статьи на unix-admin.su

быстрое изучение и написание простых скриптов на Scheme (+ пакетная обработка бесплатно) / Habr


Вступление

В статье будет рассказано о том, как в кратчайшие сроки познакомиться с основами скриптинга в GIMP на языке Scheme и приступить непосредственно к решению простых практических задач. Данный материал предназначен лишь для тех, кто собирается автоматизировать рутинную обработку здесь и сейчас, не сильно вдаваясь в тонкости и не жертвуя драгоценным временем. Также, статью не рекомендуется использовать в качестве пособия по Scheme отдельно от Script-fu. Связано это с упрощённым стилем программирования в данном материале и отсутствием освещения других немаловажных фактов, которые нас сейчас волнуют гораздо меньше, чем скорость освоения.

Содержание:

  1. Что нам понадобится?
  2. Коротко о синтаксисе
  3. Переменные
  4. Функции
  5. Списки
  6. Регистрация скрипта в GIMP
  7. Написание кода
  8. Заключение

Что нам понадобится?

Английский интерфейс: для этого достаточно создать переменную окружения «LANG» со значением «en». Зачем это нужно? Во-первых, так будет проще искать соответствие процедур объектам интерфейса. Во-вторых, мне не придется приводить команды на двух языках. В-третьих, на английском языке в интернете больше всего информации.
Консоль Script-fu: Filters → Script-fu → Console. Здесь мы сможем тестировать небольшие кусочки кода, — то, что нужно при освоении языка.
Обозреватель процедур: Help → Procedure Browser. Здесь можно без особого труда найти функцию, выполняющую требуемое действие и прочитать ее полное описание (всё хорошо задокументировано).
Редактор кода с подсветкой и/или подсчётом парных скобок. Оставлю на ваш вкус. Мне хватило Notepad++. Но учтите, скобок будет много!

В нескольких последующих секциях содержатся выдержки из первых четырех страниц документации Script-fu и немного отсебятины. Настоятельно рекомендуется попробовать запустить приведенные ниже примеры в консоли.

Коротко о синтаксисе
  • Все выражения в Scheme должны быть окружены скобками.
  • Имя функции всегда идёт первым в скобках, а затем идут её параметры.
  • Математические операторы также являются функциями.

Самое время привести пример:

(* (+ 1 2) (sqrt (- 13 4)) 10)

Последним будет посчитан результат умножения. Как видно, функции умножения передаётся три аргумента: результат сложения, результат извлечения корня из разности и число. Обратите внимание на количество скобок: они здесь везде обязательны. Это может мешать, но зато всегда понятно, что́ за чем вычисляется.

  • Функция и каждый из аргументов должны быть отделены друг от друга пробелами.

Пример: «(+ 1 2)» — корректный код, «(+1 2)» — не является таковым.

  • Всё, что идет за символом «;», является комментарием и игнорируется.

Переменные

Переменные в Scheme определяются с помощью конструкции let*. Общий вид:

(let*
 (
  (переменная значение)
  ...
  (переменная значение)
 )
 (выражение)
 ...
 (выражение)
)

Если сравнивать с императивными языками, то это что-то вроде объявления локальных переменных. Иными словами, после скобки, закрывающей конструкцию let*, переменные перестают существовать.
Пример:

(let*
 (
  (a 1)
  (b (+ a 2))
 )
 (+ a b)
)

Ещё пример:

(let*
 ( (x 9) )
 (sqrt x)
)

Обратите внимание, что даже в том случае, когда мы определяем только одну переменную, внешние скобки для списка переменных не опускаются!

Новое значение переменной можно присвоить с помощью конструкции set!:

(set! переменная значение)

Пример:

(let*
 ( (a 42) (b 21) (x 0) )
 (set! x (/ a b))
)

Функции

Свои функции можно определить с помощью конструкции define:

(define (имя_функции аргументы) код_функции)

Значением функции будет результат выполнения последней команды в коде функции.
Реализуем функцию вычисления разницы модулей (). Это можно сделать с помощью abs, но мы сделаем чуть сложнее:

(define (difference x y)
 (if (< x 0) (set! x (- x)))
 (if (< y 0) (set! y (- y)))
 (if (> x y) (- x y) (- y x))
)

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

(let* ((a 3) (b -4)) (list (difference a b) a b))

(Функция list здесь используется для вывода нескольких результатов — значения функции, переменной a и переменной b, — а подробнее о списках мы поговорим ниже). Запустите в консоли и проверьте, что значения переменных не изменились.

Списки

Чтобы определить список, достаточно написать (никаких запятых):

'(0 1 1 2 3 5 8 13)

Пустой список можно задать как через «'()», так и через «()». Списки могут содержать как атомарные значения, так и другие списки:

(let*
 (
  (x
   '("GIMP" (1 2 3) ("is" ("great" () ) ) )
  )
 )
 x
)

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

(cons 1 '(2 3 4) )

Она одинаково хорошо работает и с пустыми списками («(cons 1 () )» даст список из одного элемента).
Для создания списка, содержащего значения ранее объявленных переменных, потребуется функция list:

(let* ( (a 1) (b 2) (c 3) )
 (list a b c 4 5)
)

Чтобы понять разницу с определением списка через апостроф, замените «(list a b c 4 5)» на «'(a b c 4 5)» и сравните вывод.
Это всё хорошо, а как же получить содержимое списка? Для этого есть две функции. Первая, car, возвращает голову списка, то есть первый элемент. Вторая, cdr, возвращает хвост списка, то есть список, содержащий все элементы кроме первого. Обе функции предполагают, что список непуст. Примеры:

(car '(1 2 3 4) )
(cdr '(1 2 3 4) )
(car '(1) )
(cdr '(1) )

Вместо последовательного вызова car и cdr бывает полезно воспользоваться функциями типа caadr, cddr и т.п. Например, чтобы получить второй элемент списка, напишем следующее:

(cadr '("first" "second") )

что эквивалентно

(car (cdr '("first" "second") ) )

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

(let* ( (
 x  '( (1 2 (3 4 5) 6)  7  8  (9 10) )
 ) )
 ; здесь ваш код
)

Если у вас получилось, значит, вы уже почти готовы написать свой первый скрипт.

Регистрация скрипта в GIMP

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

Для скриптов пользователя GIMP создает в домашней директории папку .gimp-2.6/scripts. Чтобы скрипт подцепился, достаточно поместить в неё scm-файл и в меню GIMP выбрать Filters → Script-fu → Refresh Scripts (это если GIMP уже запущен, а иначе он сам всё загрузит при запуске).

В файл, очевидно, надо поместить написанные нами функции. В нём могут содержаться сколько угодно функций, но неплохо бы логически разные функции разнести по разным файлам, а файлы назвать в честь содержимого. Ещё одна рекомендация, даже соглашение: созданные нами функции должны именоваться по типу script-fu-functionname.

По большому счёту, этого уже достаточно, чтобы мы могли вызывать наши функции из консоли.

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

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

(define (script-fu-readability inImage inLayer inRadius inHigh-input))

Знаю-знаю, здесь только объявление функции, и она ничего не делает. Полезный код будет чуть позже. Сейчас нам и этого вполне достаточно. Регистрация же происходит вот так:

(script-fu-register
 "script-fu-readability"
 "Readability"
 "Improves text readability on the photos. It's needed only when there is a non-uniform illumination"
 "Dragonizer"
 "Copyleft, use it at your own sweet will"
 "January 7, 2011"
 "RGB* GRAY* INDEXED*"
 SF-IMAGE      "The image"     0
 SF-DRAWABLE   "The layer"     0
 SF-ADJUSTMENT "Median blur: radius" '(15 1 20 1 5 0 SF-SLIDER)
 SF-ADJUSTMENT "Levels: intensity of highest input" '(235 0 255 1 10 0 SF-SPINNER)
)
(script-fu-menu-register "script-fu-readability" "<Image>/Filters/User's scripts")

В первую функцию передается следующее. Первый аргумент — имя нашей функции, второй — отображаемое имя, третий — описание, четвертый — автор, пятый — сведения о копирайте, шестой — дата создания. Седьмой — типы поддерживаемых изображений (RGB, RGBA, GRAY, GRAYA, INDEXED, INDEXEDA).

Последующие аргументы являются необязательными. Они (кроме SF-IMAGE и SF-DRAWABLE) позволяют создать в окошке скрипта виджеты, такие как строчки, галки, слайдеры, спиннеры, выбор цвета, шрифта и многое другое, чтобы передать выбор пользователя в функцию. Упомянутый же SF-IMAGE передаст нам ссылку на текущее открытое изображение, а SF-DRAWABLE — на выбранный слой. Я не буду описывать все эти SF-*, их параметры вы можете посмотреть в таблицах здесь (остальное читать не нужно, ибо кратко изложено в этой статье). А ещё советую поглядеть вот эту картинку, чтобы понять, что же вам из этого понадобится (взял отсюда).

Окошко готово, осталось добавить его вызов в меню GIMP, что и делает вторая функция кода выше. Два аргумента: опять же, имя функции и путь к меню. Путь начинается с <Image>, если каких-то веток ранее не существовало, GIMP их добавит.


Ещё пример: если бы мы захотели написать скрипт, создающий изображение с заданными свойствами, мы бы убрали параметры SF-IMAGE и SF-DRAWABLE из первой функции, вместо "RGB* GRAY* INDEXED*" использовали бы пустую строку "" (нам ведь не нужно открытое изображение, мы его создадим), а во второй функции изменили бы путь на что-то вроде "<Image>/File/Create/Something".

Чтобы полюбоваться результатом, сохраним наше творчество в «script-fu-readability.scm» и обновим скрипты. Теперь откроем/создадим какое-нибудь изображение и выберем из меню наш скрипт.

Написание кода

Вот он, вожделенный момент! Но поспешу расстроить: ничего сложного тут нет. Совсем. Функции вы уже писать умеете. А всё, что вам может понадобиться от редактора, легко найти в обозревателе процедур. Нужна какая-то операция со слоями? Ищите по запросу «layer». Инвертировать изображение? Вам нужно что-то, содержащее «invert». И так далее.

Я сделаю только два замечания:

  • Очень неплохо бы заключить все действия, выполняемые скриптом, между функциями gimp-image-undo-group-start и gimp-image-undo-group-end, как это сделано ниже, чтобы пользователю не пришлось отменять каждое действие по-отдельности.
  • Все функции GIMP возвращают результатом списки, независимо от количества данных в результате. Легко проколоться, ожидая, например, layer, а получая (layer). Так что не забывайте делать car в таких случаях.

А теперь пример рабочего кода. Алгоритм я позаимствовал отсюда (спасибо Killy).

(define (script-fu-readability inImage inLayer inRadius inHigh-input)
 (let* (
   (layer2 0)
  )
  (gimp-image-undo-group-start inImage)
  (if (not (= (car (gimp-image-base-type inImage)) GRAY)) (gimp-image-convert-grayscale inImage))
  (set! layer2 (car (gimp-layer-copy inLayer FALSE)))
  (gimp-image-add-layer inImage layer2 -1)
  (plug-in-despeckle RUN-NONINTERACTIVE inImage layer2 inRadius 0 -1 256)
  (gimp-layer-set-mode layer2 DIFFERENCE-MODE)
  (set! inLayer (car (gimp-image-flatten inImage)))
  (gimp-invert inLayer)
  (gimp-levels inLayer HISTOGRAM-VALUE 0 inHigh-input 0.1 0 255)
  (gimp-image-undo-group-end inImage)
 )
)

Имея под рукой браузер процедур, разобраться здесь несложно, если интересно.

Пакетная обработка

Куда-куда? Это ещё не всё. Думаете, мы столько проделали, чтобы написать какой-то несчастный скриптик, обрабатывающий одну картинку? Да руками было бы быстрее! Так что давайте заставим GIMP открыть все файлы из заданной папки, обработать, и сохранить в другую папку.

Самое приятное — чтобы приспособить нижеприведённый код делать нечто другое, достаточно заменить вызываемую им функцию на нужную, всё остальное не изменится (ну, разве что вы захотите сохраните файл в другое расширение).

Код частично позаимствован из этого топика (спасибо Apostol), но там он сохраняет файлы, затирая исходные. Функция morph-filename взята отсюда.

(define (morph-filename orig-name new-extension)
 (let* ((buffer (vector "" "" "")))
  (if (re-match "^(.*)[.]([^.]+)$" orig-name buffer)
   (string-append (substring orig-name 0 (car (vector-ref buffer 2))) new-extension)
  )
 )
)

(define (script-fu-batch-readability inInFolder inOutFolder inRadius inHigh-input)
  (let* ((filelist (cadr (file-glob (string-append inInFolder DIR-SEPARATOR "*") 1))))
    (while (not (null? filelist))
      (let* ((filename (car filelist))
          (image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
          (layer (car (gimp-image-get-active-layer image)))
        )
        (script-fu-readability image layer inRadius inHigh-input)
        (set! layer (car (gimp-image-get-active-layer image)))
        (set! filename (string-append inOutFolder DIR-SEPARATOR
          (morph-filename (car (gimp-image-get-name image)) "png")))
        (file-png-save2 RUN-NONINTERACTIVE image layer filename filename 0 9 0 0 0 1 0 0 0)
        (gimp-image-delete image)
      )
      (set! filelist (cdr filelist))
    )
  )
)
Заключение

Скрипт Readability вместе с пакетной версией можно скачать здесь (зеркало). Код прокомментирован, даже несколько излишне.

Ещё раз напомню, что статья не претендует на полноту в широком смысле и рассчитана лишь на то, чтобы читатель мог сесть, вдумчиво прочитать, параллельно практикуясь, и начать создавать скрипты, решающие его задачи. Так, чтобы на это не ушло столько же времени, сколько требуется на более-менее качественное изучение языка.

Если вы прочитали статью до конца, то теперь вы умеете Script-fu не хуже меня.

Пишем скрипты на все случаи жизни / Habr


Каждый, кто работал сисадмином UNIX-систем, рано или поздно начинает автоматизировать свою работу с помощью скриптов.
Написаны они могут быть на чём угодно — от bash'а до tcl. Важен подход.
В этой статье я попробую вкратце описать приемы скриптовой автоматизации.

Когда нужно писать скрипты?

1. Когда это приведет к экономии времени.

Если нужно однотипно настроить 1000 свитчей, разослать спам приглашения на конференцию или собрать базу MAC-адресов — скрипты наши лучшие друзья.

2. Когда некие действия выполняются регулярно.

Архивирования резервных копий, очистка mysql-базы от мусора или сбор статистики — те самые случаи.

3. Когда нужно создать что-то сложное, но лениво делать это «по серьёзному».

Примеры — микробиллинги, счетчики трафика и системы блокировки должников.

Это нужно писать на C/C++. Но начальство сказало: «Сделать сегодня!». И снова скрипты — и мысль «когда-нибудь перепишу». 🙂

Когда не нужно писать скрипт?

Всегда, когда это не нужно согласно трём первым пунктам.

Хотя если хотите — пишите. Время ваше. 🙂

Несколько примеров из личной жизни

1. Скрипт починки всех таблиц mysql. Ставил на хостинг по крону — сразу пропали звонки абонентов на тему неработающих сайтов на mysql. [bash]

2. Массовое выполнение команд на свитчах AT-8000S. [perl]

iplist.txt — список свитчей в формате ip:login:password

command.txt — список команд.

3. Проверка работы демона — полезно при наличии падучих программ.

Можно убрать while и запихнуть в кронтаб.

4. Ежедневный бекап с распихиванием по папочкам вида <год>/<месяц>/<день>.

В кронтаб.

Заключение

Скрипты можно писать. Скрипты нужно писать. Удачи. 🙂

P.S. Извиняюсь за корявость — первый пост на Хабре.

Отправить ответ

avatar
  Подписаться  
Уведомление о