В чем разница между <<
, <<<
и < <
в bash?
Здесь документ
<<
называется структурой here-document
. Вы даете программе знать, каков будет конечный текст, и всякий раз, когда будет отображаться этот разделитель, программа будет считывать все материалы, которые вы передали программе, в качестве входных данных и выполнять над ними задачу.
Вот что я имею в виду:
$ wc << EOF
> one two three
> four five
> EOF
2 5 24
В этом примере мы говорим программе wc
для ожидания строки EOF
, затем введите пять слов, а затем введите EOF
, чтобы сообщить, что мы закончили ввод ввода. Фактически, он похож на запуск wc
сам по себе, набрав слова, а затем нажав Ctrl D
Здесь строка
<<<
известен как here-string
. Вместо того, чтобы вводить текст, вы даете предварительно созданную строку текста программе. Например, с такой программой, как bc
, мы можем сделать bc <<< 5*4
, чтобы просто получить вывод для этого конкретного случая, нет необходимости запускать bc в интерактивном режиме. Р>
Замена процесса
Как tldp.org объясняет,
Замена процесса подает вывод процесса (или процессов) в stdin другого процесса.
Таким образом, это похоже на соединение stdout одной команды с другим, например. echo foobar barfoo | wc
. Но обратите внимание: в файле bash вы увидите, что он обозначается как <(list)
. Таким образом, вы можете перенаправить вывод нескольких (!) Команд. Р>
Примечание: технически, когда вы говорите < <
, вы не имеете в виду одну вещь, но два перенаправления с одним <
и перенаправление процесса выхода из <( . . .)
. Р>
Теперь, что произойдет, если мы просто заменим процесс?
$ echo <(echo bar)
/dev/fd/63
Как вы можете видеть, оболочка создает временный файловый дескриптор /dev/fd/63
, где идет выход. Это означает, что <
перенаправляет этот файловый дескриптор в качестве ввода в команду.
Так что очень простой пример - сделать замену процессов из двух команд эха в wc:
$ wc < <(echo bar;echo foo)
2 2 8
Итак, здесь мы создаем оболочку, создаем файловый дескриптор для всего вывода, который происходит в скобках, и перенаправляем его как вход в wc
. Как ожидается, wc получает этот поток из двух команд эха, который сам будет выводить две строки , каждый из которых имеет слово, и соответственно у нас есть 2 слова, 2 строки и 6 символов плюс две подсвеченные строки.
Боковое примечание: Подстановка процесса может упоминаться как bashism (команда или структура, используемые в расширенных оболочках, таких как bash
, но не указанных POSIX) но он был реализован в ksh
до существования bash как man-страницы 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)
В приведенном выше примере вход в цикл while будет получен из команды ls
, которая может быть прочитана по очереди и echo
ed в цикле.
<()
используется для замещения процесса. Более подробную информацию и пример для <()
можно найти по этой ссылке: