Як ви використовуєте перенаправлення виводу в поєднанні з документами тут і котом?


56

Скажімо, у мене є сценарій, який я хочу передати в іншу команду або перенаправити у файл ( shпереглядаючи приклади). Припустимо, що я використовую bash.

Я можу це зробити, використовуючи echo:

echo "touch somefile
echo foo > somefile" | sh

Я також міг би зробити майже те саме, використовуючи cat:

cat << EOF
touch somefile
echo foo > somefile
EOF

Але якщо я заміню "EOF" на "EOF | sh", він просто вважає, що це частина гередока.

Як я можу зробити так, що catвиводить текст зі stdin, а потім передає його у довільне місце?


touchхіба що там, чого саме ти хочеш? просто читати вхідний файл і перенаправляти на інший за допомогою stdout?
Рахул Патіл

2
@RahulPatil звичайно, це марно. Я просто хотів приклад з кількома рядками, щоб краще проілюструвати гередок. І подивіться на приклад з використанням echo- мені було цікаво, який еквівалент цього буде використовувати cat.
strugee

Ваш приклад - це створення shсценарію з декількох рядків і передавання його безпосередньо до sh. Я знайшов, що ваш Q шукає передачу текстового виводу з декількох команд, включаючи документ ТУТ, безпосередньо до команди. Що і є другим прикладом відповіді Еша.
Дейв Х

Відповіді:


91

Існує кілька способів зробити це. Найпростіший, мабуть, такий:

cat <<EOF | sh
touch somefile
echo foo > somefile
EOF

Ще один, який приємніший синтаксис на мій погляд:

(
cat <<EOF
touch somefile
echo foo > somefile
EOF
) | sh

Це також працює, але без додаткової оболонки:

{
cat <<EOF
touch somefile
echo foo > somefile
EOF
} | sh

Більше варіацій:

cat <<EOF |
touch somefile
echo foo > somefile
EOF
  sh

Або:

{ cat | sh; } << EOF
touch somefile
echo foo > somefile
EOF

До речі, я очікую, що використання catу вашому запитанні є заповнювачем чогось іншого. Якщо ні, вийміть її так:

sh <<EOF
touch somefile
echo foo > somefile
EOF

Що можна спростити до цього:

sh -c 'touch somefile; echo foo > somefile'

або:

sh -c 'touch somefile
echo foo > somefile'

Перенаправлення виводу замість трубопроводів

sh >out <<EOF
touch somefile
echo foo > somefile
EOF

Використання catдля отримання еквівалента echo test > out:

cat >out <<EOF
test
EOF

Кілька документів тут

( cat; echo ---; cat <&3 ) <<EOF 3<<EOF2
hi
EOF
there
EOF2

Це дає результат:

hi
---
there

Ось що відбувається:

  • Оболонка бачить ( ... )і запускає вкладені команди в підзарядку.
  • Кішка і відлуння досить прості. cat <&3Каже , щоб запустити кішку з дескриптором файлу (FD) 0 (STDIN) перенаправляється з дескриптора 3; інакше кажучи, замініть вхід з fd 3.
  • Перед (...)запуском оболонки бачать два сюди документові переадресації та замінники fd 0 ( <<EOF) та fd 3 ( 3<<EOF2) з боку зчитування труб
  • Після запуску початкової команди оболонка зчитує свій stdin, поки не буде досягнуто EOF і посилає його на сторону запису першої труби
  • Далі це робиться так само з EOF2 та стороною запису другої труби

з огляду на приклад другий-останній, чи можете ви навести приклад із перенаправленням stdout замість трубопроводу?
strugee

Я відредагував відповідь на прикладі перенаправлення; це форма, яку ви хотіли відредагувати? Якщо ні, то ви можете просто дати перший рядок цієї частини для уточнення?
попіл

1
Це може допомогти зрозуміти, як оболонка обробляє це. Коли він оцінює командний рядок і знаходить << EOF, він зчитується зі стандартного вводу, поки не буде знайдений або рядок із лише EOF, або кінець введення. Все інше в початковому командному рядку, яке ще не було оброблене, продовжує оброблятись. Так, наприклад, можна зробити щось подібне: (cat; echo ---; exec <&3; cat) <<EOF 3<<EOF2 >outа потім дати введення цієї команди з двома блоками тут.
попіл

Ваше пояснення обробки шкаралупи було цікавим, але над головою :) Я хотів знати, що було б catеквівалентом echo test > out, використовуючи гередок. Тоді як ваш наведений приклад додав перенаправлення в кінці труби.
strugee

1
@OlivierDulac - я додав у відповідь кілька прикладів гередока.
попіл

1

Я просто хочу зазначити, що використання meowнастільки ж справедливе, як і EOF.

Цей сценарій додається Meow!до файлу з назвою cat:

#!/bin/sh
cat <<meow>> cat
Meow!
meow

Збережіть як catsі зробіть його виконуваним chmod +x cats, а потім запустіть його ./cats:

$ ./cats
$ cat cat
Meow!
$ ./cats
$ cat cat
Meow!
Meow!

Пояснення:

  • cat <<meowє тут синтаксисом документа . Він доручає скрипту підібрати текст тексту, який слідує за цим рядком, поки він не зустрінеться з рядком meow. Потім вміст буде виведено (або прокладено вздовж).
  • >> catтруби до файлу з іменем cat.
  • Використання >замість >>перезаписує файл замість додавання до нього.
  • Meow!- це зміст тут документа .
  • meowє кінцевим маркером для тут документа . Зміст із застосуванням >>додається до cat.

Трубопровід як до stdout, так і до файлу:

Щоб виконати запитуваний вами трубопровід, тут не потрібен документ .

catне може одночасно виводити текст і передавати текст разом, але teeце ідеальна відповідність тому, що ви просите:

echo echo | tee tee

Це буде виводити рядок echoі записувати echoу файл з назвою tee.

Ви також можете передати результат cat, якщо це є частиною вимоги, або за допомогою:

echo echo | tee tee | cat </dev/stdin

Або просто:

echo echo | tee tee | cat

Зміст файлу:

$ cat tee
echo

1
Це насправді не відповідає на питання. Також >не створює труби, як випливає з останньої кулі.
strugee

2
@strugee, >може створити труби в , zshколи той же FD перенаправляється кілька разів , як в echo foo >&1 > teeабо echo foo > tee | cat, де zshреалізує внутрішній teeдля подачі вихідного сигналу echoна обидва , catі в teeфайл.
Стефан Шазелас

Оновили свою відповідь, щоб краще відповісти на питання.
Олександр
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.