Как стать автором
Обновить

Изучение английского и старый добрый CMD

Время на прочтение7 мин
Количество просмотров4.5K
Сенсация! Сенсация! Батники позволят вам выучить английский за 10 дней Этот пост посвящен написанию скрипта для достижения крохотной личной и сугубо прикладной цели, но, как и всегда при взаимодействии с cmd, сама цель гораздо менее интересна тех странных способов и удивительных путей (какой приятный эвфемизм для так и напрашивающегося выражения), которыми она достигается.



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

Чего же мне хотелось от жизни?

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

While (not колода пуста && not надоело) do
{
	Взял случайную карточку
	Посмотрел слово
	Предложил перевод
	Перевернул карточку
	Сравнил перевод с эталоном
	If (перевод совпал с эталоном) && (слово в зубах навязло)
		удалил карточку из колоды
}


Читая документацию на английском, я неожиданно поймал себя на мысли, что в таких карточках очень нуждаюсь. Ибо слишком часто я сталкивался со следующим сценарием: встреченное неизвестное слово ищется в словаре, после чего мозг не утруждая себя лишними усилиями, сохраняет его в кеше, встраивает в контекст предложения, считывает получившееся предложение, делает некоторые умозаключения, после чего умозаключения сохраняет в ПЗУ, а все остальное стирает за ненадобностью. После третьего захода в словарь из-за одного и того же слова я понял, что пора вспомнить школьные годы и попрактиковаться в выписывании/запоминании новых слов.

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

Дизайн наше всё

Итоговое использование скрипта я видел следующим образом: в консоли в любой момент можно набрать dict [command [params] ], что в зависимости от команды:
  • <пустая команда> или show_random
    выведет случайное иностранное слово, а после нажатия любой клавиши дополнит его переводом;
  • add hello habr:приветствую, о Хабр/привет всем на хабре
    добавит в список карточек соответствующую запись(английская фраза: перевод1/перевод2/перевод3/...);
  • show_all
    отобразит все слова с их переводами
  • show hello habr
    Отобразит конкретную запись и ее перевод
  • show 23
    Аналогично show_random, но отображается не случайная запись, а с указанным номером
  • show_contents
    Выведет пронумерованный список слов, не показывая переводы
  • remove_last или rml
    Удалит последнее добавленное слово
  • remove 13 или remove hello habr (можно сокращать до rm -rf /* 13)
    Удалит тринадцатую по счету запись или же запись с указанной фразой соответственно.

Как реализовать вызов скрипта в любой момент и ежу понятно: засунуть dict.bat в любую папку, прописанную в переменной PATH. А вот весь остальной функционал некоторых людей слегка пугает. Всё дело в том, что батники издревле считаются филиалом ада на земле, где до некоторого времени банальное ветвление нужно было организовывать при помощи оператора безусловного перехода (поскольку в блоке then изначально поддерживалась только одна команда). Но всё течет и меняется, возможности cmd уже давно позволяют имитировать написание функций, что существенно расширяет наши перспективы. А делается это так:

call :myFunction %param1% %param2% %param3% …

:myFunction
echo Hello, Habr!
exit /b


Для возвращения результатов работы можно пользоваться «глобальными» переменными, но для тонких ценителей есть более интересное решение – засовывать результат в код возврата. Впрочем, чаще всего это всё равно требует использование переменной, однако спасает от необходимости помнить ее имя. Маленький пример:

@echo off
call :Answer_to_the_Ultimate_Question_of_Life_the_Universe_and_Everything
echo %errorlevel%
exit /b

:Answer_to_the_Ultimate_Question_of_Life_the_Universe_and_Everything
set SIX=1+5
set NINE=8+1
set /a ANSWER=%SIX%*%NINE%
exit /b %ANSWER%


Тяжела и неказиста жизнь дурного программиста

Но вернемся к изначальному скрипту. Функция add в нулевом приближении была проста до безумия – она запихивала получаемую в качестве параметра строку в файл vocabulary:

echo %* >> vocabulary || exit /b 1


Однако для такой операции мы должны находиться в каталоге со скриптом, а не в каталоге из которого скрипт был вызван. Для этого есть пара важных трюков: во-первых, этот каталог можно узнать при помощи нулевого параметра скрипта (%0) с нужными модификаторами и кавычками на случай неожиданных пробелов(“%~dp0”). Но даже зная его, мы не можем выполнить банальное cd “%~dp0”, т. к. команда даст нежелательный результат в случае а) расположения скрипта на другом жестком диске (попробуйте сделать cd D:\temp находясь на C:\, будете приятно удивлены), либо б) расположения скрипта на сетевом ресурсе. К счастью, оба случая нивелируются уличной магией команды pushd “%~dp0”.

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



Забавно, не так ли? Я знаю только один способ это сделать: функцию « echo. », переводящую курсор на следующую строку, можно вызвать с параметрами. Конструкция «echo.ON» всё-таки выполнит эту сложнейшую для cmd задачу. Собственно, к чему это я? Случайный вызов dict add без параметров развлечет вас очень странной новой записью, если к echo не добавить точку. Впрочем, доработка напильником добавила минимальную проверку на корректность вводимой строки, что отмело подобные выходки. Но в других областях этого скрипта эта проблема и ее решение полностью сохраняются. Советую во всех случаях вывода сообщений использовать только echo. как более предсказуемую.

Функция show_all реализуется элементарно: при помощи цикла for с ключом /f она пробегает по vocabulary и каждую строку отдает парсеру, который выводит ее с нужным форматированием используя аналогичный цикл. Всё это скучно. А вот вывод записи по ее номеру, что крайне нужно самой востребованной функции show_random, воплощать было несколько любопытнее. Выдрать из текстового файла определенную строку средствами cmd, казалось, будет сложно. Но решение оказалось вполне себе простым и доступным, только для его обнаружения нужно было хорошо знать возможности утилиты findstr. А именно, нас интересует нумерация строк в результатах поиска: производим поиск по маске «все возможные строки» (.*) с ключом /n (нумерация), получаем фактически нумерованный файл vocabulary, результат засовываем в цикл for, выдираем пары (номер строки/сама строка), а дальше уже дело техники.

Кроме прочего, в процессе копания в данном скрипте я обнаружил еще одно забавное обстоятельство. Некоторым людям катастрофически не хватает возможности создавать комментарии не построчно, а блоками (по аналогии с /*таким комментарием*/). Но любой текст, написанный в области, которая никогда не будет исполняться, обладает всеми необходимыми свойствами. Таким образом комментировать текст можно, например, и так:
goto EndofComment
Comment 1
Comment 2

:EndofComment


Или пользоваться естественными областями. А вот с полюбившимися многим комментариями :: нужный текст, оказывается, есть серьезные проблемы

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

Не уверен, что скрипт пригодится многим, но всё же стоит отметить: его область применения несколько шире заявленной. При желании, он может помочь заучить любые пары термин/объяснение (гипогликемия: снижение концентрации глюкозы в крови) или, скажем, пол правила/вторая половина правила (Жи-Ши: пиши через И). Ну и, в любом случае, главная цель всего этого мероприятия – получение удовольствия – лично для меня была выполнена. Очень надеюсь, что и вы разделили его со мной. На этой замечательной ноте я, пожалуй, завершу статью обещанным дисклеймером.

Дисклеймер

Формат и тема статьи далеко не новы, что позволяет воспользоваться статистически обоснованным опытом предыдущих авторов и сразу ответить на десяток-другой НУ ОЧЕНЬ распространенных вопросов

1. Уважаемый автор, где вы нашли руки достаточной кривизны для написания такой статьи/скрипта? Здесь же <список-непростительных-и-ужасных-ошибок>
Не стреляйте в пианиста, он играет как умеет. За конструктивную критику всегда искренне благодарен, но я вряд ли смогу соответствовать запросам достаточно искушенных людей. Пост является пробой пера, а скрипты – маленьким хобби. Пожалуйста, относитесь к ним соответствующе.

2. Я ничего не понял/я и так всё знаю. Зачем вы всё это понаписали тут?
Как это ни прискорбно, информация не может быть сверхинтересной для всех представителей человеческой расы хабраобщества в силу наличия личных предпочтений и разницы в имеющихся знаниях. Если вы задаете этот вопрос, искренне прошу прощения за потраченное время, статья предназначалась не вам. Называйте меня наивным оптимистом, но я верю, что множество людей не задающих этот вопрос не пусто.

3. Ну хорошо, для кого статья мы выяснили. А скрипт то кому нужен? Его практическая польза пренебрежимо мала.
Цель именно данного скрипта – расширение словарного запаса пользователя – является больше поводом покопаться в возможностях старичка-калеки CMD и впихнуть невпихуемое решить кучу возникающих проблем при помощи тех или иных костылей. Приятная и интересная разминка для мозга.

4. А вы вообще в курсе, что при помощи моего любимого <bash/powershell/etc> такие задачи решаются в полстроки?
Судя по распространенности этого вопроса, без такого холивара жизнь теряет всю свою остроту и краски. Но давайте всё же ради разнообразия попробуем его избежать. CMD является отличным местом для концентрированных костылей и хаков, именно их иногда очень не хватает в свободное от работы время. Цель подобных задач получить fun. В некоторых случаях кроме fun’a получается еще и что-то полезное.

5. Мне кажется, эта статья не нова и опирается на кучу других источников.
Безусловно. Она имеет множество важных идейных вдохновителей, привнесших в нее, равно как и в моё мировоззрение, свою частичку, и имя им Легион. Но одного я не могу не выделить среди прочих, это небезызвестная здесь статья уроки batаники.
Теги:
Хабы:
Всего голосов 31: ↑25 и ↓6+19
Комментарии21

Публикации