среда, 6 июля 2011 г.

Опасайтесь цифр перед оператором перенаправления

Это перевод Beware of digits before the redirection operator. Автор: Реймонд Чен.

Если вы хотите записать строку "Meet at 2" в файл schedule, вы можете попытаться использовать
echo Meet at 2>schedule
Но если вы попробуете это выполнить, то вы увидите строку "Meet at" на экране, а файл schedule будет пуст.

Что произошло?

Цифра перед оператором перенаправления модифицирует поток, к которому применяется оператор. Если вы собираетесь перенаправить альтернативный выходной поток, это почти всегда будет стандартный error-поток - поток с номером 2. К примеру, чтобы вывести поток ошибок в файл, вы можете написать что-то такое:
sort /invalidswitch 2>errorfile
есть также оператор ">&", который переоткрывает поток как другой поток. Идиома
some-command >output 2>&1
говорит: "Помести нормальный вывод в файл output, а затем измени поток вывода ошибок (2), чтобы он ссылался на обычный поток вывода (1)". В результате оба потока (обычный и выходной) будут записаны в файл output.

Но что если вам нужно было записать строку "Meet at 2" в файл schedule? (прим.пер.: вы не можете использовать кавычки, потому что echo выводит строку "как есть")

Вы можете вставить пробел между "2" и ">". Это работает для большинства программ, поскольку они просто игнорируют ведомые пробелы в командных строках, но это был вопрос с подвохом: команда echo является одной из тех команд, что обращает внимание на ведомые пробелы. В результате содержимое файла schedule будет "Meet at 2<пробел><cr><lf>". Быть может, это достаточно для вас - тогда вы можете пропустить следующий абзац.

Не хотите ведомый пробел в файле? Для этого вам нужно использовать метасимвол экранирования - ^:
echo Meet at ^2>schedule

Последнее "ага!" здесь - эта противная 2 может придти из переменной окружения:
set message=Meet at 2
echo %message%>schedule
Ведомая 2 в %message% будет взаимодействовать со знаком больше или равно, приводя к непредусмотренному перенаправлению. Чтобы решить эту проблему, вы можете использовать пробел между переменной и знаком ">" - в предположении, что вы находитесь в сценарии, где лишний пробел вас устраивает (а если нет, то мы посмотрим на обходной трюк в следующий раз).

Заметьте, что если вы собираетесь использовать переменную окружения, чьё содержимое не находится под вашим контролем, и развернуть её в командную строку без фильтра, то у вас будут гораздо более серьёзные проблемы, чем просто ведомая цифра, портящая перенаправление. Кто-то может решить, что %message% должно быть "&format C: /y". Вставка этого в командную строку без попыток фильтрации данных приведёт к выполнению
echo &format C: /y>schedule
что является отличным способом испортить чей-то день (ну, OKей, вы не можете отформатировать диск с файлом подкачки, но вы поняли идею).

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

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