Previous Entry Share Next Entry
Еще про Шелл
zhtw
Давайте я расскажу про другую интересную конструкцию на Шелле. Теперь про такую, которая работает.
Иногда нужно выполнить кое-какие действия над файлом и результат положить в два разных файла. При этом действия легко сделать за один проход.

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


rm -f out2
while read x y; do
  echo $x
  echo $y >>out2
done >out1 <in


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

Как написать хорошо? Элементарно!


while read x y; do
  echo $x
  echo $y >&3
done >out1 3>out2 <in


Разве это не прекрасно? (Я понимаю, что код по-прежнему внешне не симметричен, но нас интересует внутренняя красота: логика работы с out1 и out2 -- одинаковая.)

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

  • 1
> в шелле можно перегружать не только стандартный ввод и вывод (и вывод об ошибках), а вообще любые дискрипторы!

Ну, не знаю, Лёша. Подобный постулат звучит очень странно. Кто будет открывать эти дескрипторы, и какого типа файловым объектам они будут соответствовать? Сдается мне, у тебя просто шелл уже открыл что-то, чему система присвоила третий дескриптор, и только поэтому это и работает. Вот что у меня в интерактивном баше происходит:

$ echo foo >&3
bash: 3: Bad file descriptor

> Сдается мне, у тебя просто шелл уже открыл что-то, чему система присвоила...

Что значит «сдается мне»? В скрипте явно написано: перегрузить третий дискриптор в файл.

А у тебя третий дискриптор не открыт, отсюда и ошибка.

  • 1
?

Log in