Каково различие между <<, <<<и <<в ударе?

Между чем различие <<, <<< и < < в ударе?

108
задан 7 February 2017 в 09:43

4 ответа

Здесь документ

<< известен как 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)
121
ответ дан 22 November 2019 в 23:00

< < является синтаксической ошибкой:

$ cat < <
bash: syntax error near unexpected token `<'

< <() - это процесс замещения (<()) в сочетании с перенаправлением (<):

[ 1110] Придуманный пример:

$ wc -l < <(grep ntfs /etc/fstab)
4
$ wc -l <(grep ntfs /etc/fstab)
4 /dev/fd/63

При замене процесса путь к дескриптору файла используется как имя файла. Если вы не хотите (или не можете) использовать имя файла напрямую, вы объединяете подстановку процесса с перенаправлением.

Чтобы было ясно, нет оператора < <.

26
ответ дан 22 November 2019 в 23:00

< < синтаксическая ошибка, Вы, вероятно, имеете в виду command1 < <( command2 ), который является простым перенаправлением ввода, сопровождаемым заменой процесса, и очень похож, но не эквивалентен:

command2 | command1

различие, принимающее Вас, работает bash, command1, выполняется в подоболочке во втором случае, в то время как это выполняется в текущей оболочке в первой. Это означает, что сет переменных в command1 не был бы проигран с вариантом замены процесса.

12
ответ дан 22 November 2019 в 23:00

< < даст синтаксическую ошибку. Надлежащее использование следующие:

Объяснение с помощью примеров:

Пример для < <():

while read line;do
   echo $line
done< <(ls)

В вышеупомянутом примере, вход к циклу с условием продолжения прибудет из эти ls команда, которая может быть считана линию за линией и echo редактор в цикле.

<() используется для замены процесса. Больше информации и примера для <() могут быть найдены в этой ссылке:

замена Процесса и канал

11
ответ дан 22 November 2019 в 23:00

Другие вопросы по тегам:

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