В чем разница между <<
, <<<
и < <
в Баш?
command-line
bash
redirect
Searene
источник
источник
Ответы:
Здесь документ
<<
известен какhere-document
структура. Вы даете программе знать, каким будет конечный текст, и всякий раз, когда этот разделитель виден, программа считывает все данные, которые вы дали программе, в качестве входных данных и выполняет над ним задачу.Вот что я имею в виду:
В этом примере мы говорим
wc
программе дождатьсяEOF
строки, затем введите пять слов, а затем введите,EOF
чтобы сообщить, что мы закончили ввод данных. По сути, это похоже на самодельный запускwc
, набрав слова, затем нажавCtrlDВ bash они реализуются через временные файлы, обычно в форме
/tmp/sh-thd.<random string>
, тогда как в dash они реализуются как анонимные каналы. Это можно наблюдать с помощью отслеживания системных вызовов с помощьюstrace
команды. Заменитеbash
на,sh
чтобы увидеть, как/bin/sh
выполняется это перенаправление.Здесь строка
<<<
известен какhere-string
. Вместо того, чтобы вводить текст, вы даете предварительно подготовленную строку текста программе. Например, с такой программой, которуюbc
мы можем сделать,bc <<< 5*4
чтобы просто получить вывод для этого конкретного случая, нет необходимости запускать bc в интерактивном режиме.Здесь строки в bash реализуются через временные файлы, как правило, в формате
/tmp/sh-thd.<random string>
, который впоследствии не связывается, что делает их временно занимающими некоторое пространство памяти, но не отображаются в списке/tmp
записей каталога, и фактически существуют как анонимные файлы, которые все еще могут на него можно ссылаться через дескриптор файла самой оболочкой, и этот дескриптор файла наследуется командой и впоследствии дублируется на дескриптор файла 0 (stdin) черезdup2()
функцию. Это можно наблюдать черезИ через трассировку системных вызовов (вывод сокращен для удобства чтения; обратите внимание, как временный файл открывается как fd 3, данные записываются в него, затем он снова открывается с
O_RDONLY
флагом как fd 4 и позже не связывается, затемdup2()
на fd 0, который наследуетсяcat
позднее ):Мнение: возможно, потому что здесь строки используют временные текстовые файлы, это является возможной причиной, по которой здесь-строки всегда вставляют завершающий символ новой строки, так как текстовый файл по определению POSIX должен иметь строки, заканчивающиеся символом новой строки.
Процесс замены
Как объясняет tldp.org ,
Таким образом, в действительности это похоже на передачу стандартного вывода одной команды другой, например
echo foobar barfoo | wc
. Но обратите внимание: на странице руководства bash вы увидите, что она обозначена как<(list)
. Таким образом, вы можете перенаправить вывод нескольких (!) Команд.Примечание: технически, когда вы говорите, что
< <
вы имеете в виду не одну вещь, а два перенаправления с одним<
и перенаправление процесса из вывода<( . . .)
.Что произойдет, если мы просто заменим процесс?
Как видите, оболочка создает временный файловый дескриптор,
/dev/fd/63
куда направляется вывод (который, согласно ответу Жиля , является анонимным каналом). Это означает,<
что перенаправляет этот дескриптор файла в качестве ввода в команду.Очень простой пример - сделать подстановку процесса из двух команд echo в wc:
Таким образом , здесь мы делаем оболочки создать дескриптор файла для всех вывод , что происходит в круглых скобках и перенаправлять , что в качестве вклада в
wc
.Как ожидается, туалет получает тот поток из двух эхо - команд, что само по себе будет выводить две линии, каждая из которых имеет слово, и соответственно у нас есть 2 слова, 2 строки и 6 символов плюс две новые строки.Дополнительное примечание: Подстановка процесса может упоминаться как bashism (команда или структура, используемая в расширенных оболочках, например
bash
, но не указанная в POSIX), но она была реализованаksh
до существования bash как страница руководства ksh, и этот ответ предполагает. Снаряды любятtcsh
иmksh
не имеют процесса замены. Итак, как мы могли бы перенаправить вывод нескольких команд в другую команду без подстановки процесса? Группировка плюс обвязка!По сути, это то же самое, что и в предыдущем примере. Однако это не так, как замена процесса, поскольку мы делаем стандартный вывод всей подоболочки и стандартный
wc
связью с каналом . С другой стороны, подстановка процесса заставляет команду прочитать временный дескриптор файла.Так что, если мы можем сделать группировку с трубопроводом, зачем нам нужна замена процесса? Потому что иногда мы не можем использовать трубопровод. Рассмотрим приведенный ниже пример - сравнение выходных данных двух команд с
diff
(которым нужны два файла, и в этом случае мы даем ему два файловых дескриптора)источник
< <
используется, когда кто-то получает стандартный вывод из процесса подстановки . Такая команда может выглядеть следующим образом :cmd1 < <(cmd2)
. Например,wc < <(date)
< <
Само по себе не вещь , в случае замены процесса это просто<
сопровождается чем-то еще, что начинается с<
<<<
сначала был реализован порт Unix оболочки Plan 9 rc, а затем принят zsh, bash и ksh93. Я бы тогда не назвал это башизмом.echo 'foo' | read; echo ${REPLY}
будет не возвращатьсяfoo
, потому чтоread
начинается в суб-оболочки - трубопровод начинает подоболочку. Тем не менее,read < <(echo 'foo'); echo ${REPLY}
правильно возвращаетсяfoo
, потому что нет вложенной оболочки.< <
это синтаксическая ошибка:< <()
Является ли процесс замены (<()
) в сочетании с перенаправлением (<
):Придуманный пример:
При замене процесса путь к дескриптору файла используется как имя файла. Если вы не хотите (или не можете) использовать имя файла напрямую, вы объединяете подстановку процесса с перенаправлением.
Чтобы было ясно, нет
< <
оператора.источник
<()
дает имя, похожее на имя файла, поэтому оно более полезно -< <()
заменяет стандартный ввод, когда это может не понадобиться. Вwc
последнем случае оказывается более полезным. Это может быть менее полезным в других местах< <
это синтаксическая ошибка, вы, вероятно, имеете в виду,command1 < <( command2 )
что это простое перенаправление ввода с последующей подстановкой процесса и очень похоже, но не эквивалентно:Разница в том, что вы работаете,
bash
заключаетсяcommand1
в том, что во втором случае он запускается в подоболочке, а в первом - в текущей оболочке. Это означает, что переменные, установленные вcommand1
, не будут потеряны с вариантом замены процесса.источник
< <
выдаст синтаксическую ошибку. Правильное использование заключается в следующем:Объясняя с помощью примеров:
Пример для
< <()
:В приведенном выше примере вход в цикл while будет поступать из
ls
команды, которую можно читать построчно иecho
редактировать в цикле.<()
используется для замены процесса. Дополнительную информацию и пример<()
можно найти по этой ссылке:Процесс замещения и трубы
источник