Операторы перенаправления всегда открывают дескрипторы файлов параллельно?

Можно снабдить префиксом большинство команд sed адрес для ограничения строк, к которым они применяются. Адрес может быть номером строки или regex, разграниченным /.

cat INPUT | sed '/Select ASDF/ s=sdfg=XXXX='

Как упомянутый Peter. O, команда, как записано выше заменит первым вхождением любого sdfg в строке, содержащей Select ASDF. Если необходимо заменить точным совпадением sdfg только в случае это находится в четвертом столбце, необходимо пойти этим путем:

cat INPUT | sed 's/\(^Select ASDF [^ ]* \)sdfg /\1XXXX /'

7
12.06.2013, 12:15
2 ответа

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

Программа запущена с тремя открытыми файлами: stdin (#0), stdout (#1), и stderr (#2). Если Вы просто запустите программу от своего приглашения оболочки, то они будут подключены к Вашему оконечному устройству, таким образом, программа считает то, что Вы вводите (stdin), и печать производит (stdout) и ошибки (stderr) к Вашему терминалу.

Как пример, я просто работаю cat в терминале (который tty говорит /dev/pts/31). Я могу проверить, с какими файлами это имеет открытый lsof:

$ lsof -a -p `pidof cat` -d0,1,2
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
cat     21257 anthony    0u   CHR 136,31      0t0   34 /dev/pts/31
cat     21257 anthony    1u   CHR 136,31      0t0   34 /dev/pts/31
cat     21257 anthony    2u   CHR 136,31      0t0   34 /dev/pts/31

Действительно, мы видим, что это имеет терминал, открытый для всех трех. Теперь, вместо этого, давайте попробуем довольно глупый вызов кошки: cat < /dev/zero > /dev/null 2>/dev/full, который перенаправляет все три:

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
cat     21838 anthony    0r   CHR    1,5      0t0 1030 /dev/zero
cat     21838 anthony    1w   CHR    1,3      0t0 1028 /dev/null
cat     21838 anthony    2w   CHR    1,7      0t0 1031 /dev/full

Оболочка реализовала те перенаправления путем передачи этих трех устройств как stdin, stdout, и stderr (вместо терминала). Оболочка так же реализует каналы. Давайте попробуем cat | dd > /dev/null (довольно глупый канал, действительно):

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     22507 anthony    0u   CHR 136,31      0t0       34 /dev/pts/31
cat     22507 anthony    1w  FIFO    0,8      0t0 56081395 pipe
cat     22507 anthony    2u   CHR 136,31      0t0       34 /dev/pts/31

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
dd      22508 anthony    0r  FIFO    0,8      0t0 56081395 pipe
dd      22508 anthony    1u   CHR 136,31      0t0       34 /dev/null
dd      22508 anthony    2u   CHR 136,31      0t0       34 /dev/pts/31

Заметьте, как оболочка открыла канал, и она использовала его для соединения stdout cat к stdin dd. И далее как это соединилось ddstdout к /dev/null.

Выполняемые команды действительно не знают о перенаправлениях. Они просто используют stdin, stdout, stderr как нормальный. Это мог все быть терминал, или они могли быть перенаправлены в файл, устройство или возможно канал к другой программе. Или даже сетевой сокет, если Ваши поддержки оболочки это.

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

(ПРИМЕЧАНИЕ: Некоторые программы ведут себя по-другому в случае, где один из тех привязан к терминалу, но это должно обычно быть более удобным для пользователя в интерактивном использовании, Например, ls переключатели к выводу отдельного столбца и никакому цвету, когда stdout не является терминалом — который обычно является, что Вы хотите, если Вы собираетесь передать его другой программе. Некоторый дескриптор программ, запрашивающий по-другому, если stdin не является терминалом. И так далее.)

11
27.01.2020, 20:14
  • 1
    @derobert! Это было большим объяснением. Я озирался, если был способ проверить как cat незаметные работы, и к счастью Вы проиллюстрировали это. –  Kent Pawar 14.06.2013, 17:59

Перенаправление происходит сначала в оболочке. В Вашем примере:

cat test.txt > test.txt

Первой вещью, которая происходит, является удар, открывается test.txt, который усекает файл. Это теперь пусто, прежде cat выполняется с test.txt как аргумент.

От раздела перенаправления страницы справочника удара:

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

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

10
27.01.2020, 20:14

Теги

Похожие вопросы