Здесь документ
<<
известен как here-document
структура. Вы сообщаете программе, что будет конечным текстом, и каждый раз, когда тот разделитель замечен, программа считает весь материал, который Вы дали программе, как введено и выполняете задачу на нее.
Вот то, что я имею в виду:
$ wc << EOF
> one two three
> four five
> EOF
2 5 24
В этом примере мы говорим wc
программа для ожидания EOF
строка, затем введите в пяти словах и затем введите EOF
сигнализировать, что мы сделаны, дав вход. В действительности это подобно выполнению wc
отдельно, вводя в словах, затем при нажатии CtrlD
В ударе они реализованы через временные файлы, обычно в форме /tmp/sh-thd.<random string>
, в то время как в тире они реализованы как неименованные каналы. Это может наблюдаться через трассировку системных вызовов с strace
команда. Замена bash
с sh
видеть как /bin/sh
выполняет это перенаправление.
$ strace -e open,dup2,pipe,write -f bash -c 'cat <<EOF
> test
> EOF'
Здесь строка
<<<
известен как here-string
. Вместо того, чтобы ввести в тексте, Вы даете предварительно сделанную строку текста к программе. Например, с такой программой как bc
мы можем сделать bc <<< 5*4
просто быть произведенным для того конкретного случая, никакая потребность работать до н.э в интерактивном режиме.
Здесь-строки в ударе реализованы через временные файлы, обычно в формате /tmp/sh-thd.<random string>
, которые являются позже несвязанными, таким образом заставляя их занять некоторое пространство памяти временно, но не обнаружиться в списке /tmp
записи каталога, и эффективно существуют как анонимные файлы, на которые может все еще сослаться через дескриптор файла сама оболочка, и что дескриптор файла, наследованный командой и позже, копировал на дескриптор файла 0 (stdin) через dup2()
функция. Это может наблюдаться через
$ ls -l /proc/self/fd/ <<< "TEST"
total 0
lr-x------ 1 user1 user1 64 Aug 20 13:43 0 -> /tmp/sh-thd.761Lj9 (deleted)
lrwx------ 1 user1 user1 64 Aug 20 13:43 1 -> /dev/pts/4
lrwx------ 1 user1 user1 64 Aug 20 13:43 2 -> /dev/pts/4
lr-x------ 1 user1 user1 64 Aug 20 13:43 3 -> /proc/10068/fd
И через трассировку syscalls (вывод, сокращенный для удобочитаемости; заметьте, как временный файл открыт как fd 3, данные, записанные в него, затем это вновь открыто с O_RDONLY
отметьте как fd 4 и позже несвязанный, затем dup2()
на fd 0, который наследован cat
позже):
$ strace -f -e open,read,write,dup2,unlink,execve bash -c 'cat <<< "TEST"'
execve("/bin/bash", ["bash", "-c", "cat <<< \"TEST\""], [/* 47 vars */]) = 0
...
strace: Process 10229 attached
[pid 10229] open("/tmp/sh-thd.uhpSrD", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
[pid 10229] write(3, "TEST", 4) = 4
[pid 10229] write(3, "\n", 1) = 1
[pid 10229] open("/tmp/sh-thd.uhpSrD", O_RDONLY) = 4
[pid 10229] unlink("/tmp/sh-thd.uhpSrD") = 0
[pid 10229] dup2(4, 0) = 0
[pid 10229] execve("/bin/cat", ["cat"], [/* 47 vars */]) = 0
...
[pid 10229] read(0, "TEST\n", 131072) = 5
[pid 10229] write(1, "TEST\n", 5TEST
) = 5
[pid 10229] read(0, "", 131072) = 0
[pid 10229] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=10229, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
Мнение: потенциально, потому что здесь строки используют временные текстовые файлы, это - возможная причина, почему здесь-строки всегда вставляют запаздывающую новую строку, так как текстовый файл по определению POSIX должен иметь строки тот конец в символе новой строки.
Замена процесса
Поскольку tldp.org объясняет,
Замена процесса подает вывод процесса (или процессов) в stdin другого процесса.
Таким образом, в действительности это подобно передаче по каналу stdout одной команды к другому, например. echo foobar barfoo | wc
. Но уведомление: в странице справочника удара Вы будете видеть, что она обозначена как <(list)
. Так в основном можно перенаправить вывод нескольких (!) команд.
Примечание: технически, когда Вы говорите < <
Вы не обращаетесь к одной вещи, но двум перенаправлениям с синглом <
и перенаправление процесса вывода от <( . . .)
.
Теперь, что происходит, если мы действительно просто обрабатываем замену?
$ echo <(echo bar)
/dev/fd/63
Как Вы видите, оболочка создает временный дескриптор файла /dev/fd/63
куда вывод идет (который согласно ответу Gilles, неименованный канал). Это означает <
перенаправления, что дескриптор файла, как введено в команду.
Таким образом, очень простой пример состоял бы в том, чтобы сделать замену процесса вывода от двух команд эха в туалет:
$ wc < <(echo bar;echo foo)
2 2 8
Таким образом, здесь мы заставляем оболочку создать дескриптор файла для всего вывода, который происходит в круглой скобке, и перенаправьте это, как введено к wc
.As ожидал, туалет получает тот поток от двух команд эха, которые отдельно произвели бы две строки, каждый перебрасывание парой слов, и соответственно у нас есть 2 слова, 2 строки и 6 символов плюс две считаемые новых строки.
Примечание стороны: замена Процесса может упоминаться как bashism (команда или структура, применимая в усовершенствованных оболочках как bash
, но не указанный POSIX), но это было реализовано в ksh
перед существованием удара, поскольку предлагают ksh страница справочника и этот ответ. Оболочки как tcsh
и mksh
однако не имейте замены процесса. Таким образом, как мы могли обойти вывод перенаправления нескольких команд в другую команду без замены процесса? Группировка плюс передача по каналу!
$ (echo foo;echo bar) | wc
2 2 8
Эффективно это совпадает с выше примера, Однако это отличается под капотом от замены процесса, так как мы делаем stdout целой подоболочки и stdin wc
связанный с каналом. С другой стороны, замена процесса заставляет команду считать временный дескриптор файла.
Таким образом, если мы можем сделать группировку с передачей по каналу, почему мы должны обработать замену? Поскольку иногда мы не можем использовать передачу по каналу. Рассмотрите пример ниже - сравнение выводов двух команд с diff
(которому нужны два файла, и в этом случае мы даем ему два дескрипторов файлов),
diff <(ls /bin) <(ls /usr/bin)
< <
является синтаксической ошибкой:
$ cat < <
bash: syntax error near unexpected token `<'
< <()
- это процесс замещения (<()
) в сочетании с перенаправлением (<
):
$ wc -l < <(grep ntfs /etc/fstab)
4
$ wc -l <(grep ntfs /etc/fstab)
4 /dev/fd/63
При замене процесса путь к дескриптору файла используется как имя файла. Если вы не хотите (или не можете) использовать имя файла напрямую, вы объединяете подстановку процесса с перенаправлением.
Чтобы было ясно, нет оператора < <
.
< <
синтаксическая ошибка, Вы, вероятно, имеете в виду command1 < <( command2 )
, который является простым перенаправлением ввода, сопровождаемым заменой процесса, и очень похож, но не эквивалентен:
command2 | command1
различие, принимающее Вас, работает bash
, command1
, выполняется в подоболочке во втором случае, в то время как это выполняется в текущей оболочке в первой. Это означает, что сет переменных в command1
не был бы проигран с вариантом замены процесса.
< <
даст синтаксическую ошибку. Надлежащее использование следующие:
Объяснение с помощью примеров:
Пример для < <()
:
while read line;do
echo $line
done< <(ls)
В вышеупомянутом примере, вход к циклу с условием продолжения прибудет из эти ls
команда, которая может быть считана линию за линией и echo
редактор в цикле.
<()
используется для замены процесса. Больше информации и примера для <()
могут быть найдены в этой ссылке: