Jak korzystać z przekierowania wyjściowego w połączeniu z dokumentami tutaj i cat?

56

Powiedzmy, że mam skrypt, który chcę potokować do innej komendy lub przekierować do pliku (do potoków shdla przykładów). Załóżmy, że używam bash.

Mógłbym to zrobić za pomocą echo:

echo "touch somefile
echo foo > somefile" | sh

Mógłbym również zrobić prawie to samo, używając cat:

cat << EOF
touch somefile
echo foo > somefile
EOF

Ale jeśli zamienię „EOF” na „EOF | sh”, to po prostu pomyśli, że to część heredoc.

Jak mogę to zrobić, aby catwypisywać tekst ze standardowego wejścia, a następnie przesyłać go do dowolnej lokalizacji?

strugee
źródło
touchjest chyba, że ​​tam jest, czego dokładnie chcesz? jest po prostu czytać plik wejściowy i przekierowywać do innego przy pomocy stdout?
Rahul Patil
2
@RahulPatil oczywiście jest bezużyteczny. Chciałem tylko przykład z więcej niż jedną linią, aby lepiej zilustrować heredoc. I spójrz na przykład przy użyciu echo- zastanawiałem się, jaki byłby odpowiednik tego cat.
strugee
Twoim przykładem jest tworzenie shskryptu z wielu ciągów i przekazywanie go bezpośrednio do sh. Znalazłem twoje Q szukające przekazania wyniku tekstowego wielu poleceń, w tym TUTAJ dokumentu, bezpośrednio do polecenia. Tak właśnie robi drugi przykład odpowiedzi Asha.
Dave X

Odpowiedzi:

91

Można to zrobić na wiele sposobów. Najprostszy jest prawdopodobnie taki:

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

Kolejna, moim zdaniem, ładniejsza składnia:

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

Działa to również, ale bez podpowłoki:

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

Więcej wariantów:

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

Lub:

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

Nawiasem mówiąc, oczekuję, że użycie catw twoim pytaniu jest symbolem zastępczym dla czegoś innego. Jeśli nie, wyjmij go w następujący sposób:

sh <<EOF
touch somefile
echo foo > somefile
EOF

Co można uprościć do tego:

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

lub:

sh -c 'touch somefile
echo foo > somefile'

Przekierowanie wyjścia zamiast potoku

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

Używanie w catcelu uzyskania odpowiednika echo test > out:

cat >out <<EOF
test
EOF

Wiele dokumentów tutaj

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

Daje to wynik:

hi
---
there

Oto co się dzieje:

  • Powłoka widzi ( ... )i uruchamia załączone polecenia w podpowłoce.
  • Kot i echo są dość proste. cat <&3Mówi uruchomić kot z deskryptora pliku (fd) 0 (stdin) przekierowany z fd 3; innymi słowy, wyjmij dane wejściowe z fd 3.
  • Przed (...)uruchomieniem powłoka widzi dwa przekierowania dokumentu tutaj i zastępuje fd 0 ( <<EOF) i fd 3 ( 3<<EOF2) stroną odczytu potoków
  • Po uruchomieniu polecenia początkowego powłoka odczytuje swoje standardowe wejście, aż do osiągnięcia EOF i przesyła je do strony zapisu pierwszego potoku
  • Następnie robi to samo z EOF2 i stroną zapisującą drugiego potoku
popiół
źródło
biorąc pod uwagę przykład przedostatni, czy możesz podać przykład z przekierowaniem standardowym zamiast potokowania?
strugee
Zredagowałem odpowiedź za pomocą przykładu przekierowania; czy to jest formularz, który chciałeś edytować? Jeśli nie, czy możesz podać pierwszy wiersz tej części, aby wyjaśnić?
ash
1
Pomoże to zrozumieć, w jaki sposób powłoka przetwarza to. Podczas oceny wiersza polecenia i znalezienia << EOF, odczytuje ze standardowego wejścia, dopóki nie zostanie znaleziony wiersz zawierający tylko EOF, lub koniec wejścia. Wszystkie pozostałe elementy oryginalnego wiersza poleceń, które nie zostały jeszcze przetworzone, są następnie przetwarzane. Na przykład można zrobić coś takiego: (cat; echo ---; exec <&3; cat) <<EOF 3<<EOF2 >outa następnie podać dane polecenia za pomocą dwóch bloków tutaj w rzędzie.
ash
Twoje wyjaśnienie przetwarzania powłoki było interesujące, ale nad moją głową :) Chciałem wiedzieć, co byłoby catrównoważne z echo test > outużyciem heredoc. Natomiast podany przykład dodał przekierowanie na końcu potoku.
strugee
1
@OlivierDulac - Do odpowiedzi dodałem przykładowy heredoc.
ash
1

Chcę tylko zauważyć, że używanie meowjest tak samo ważne jak EOF.

Ten skrypt zostanie dołączony Meow!do pliku o nazwie cat:

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

Zapisz jako catsi zrób to za pomocą chmod +x cats, a następnie uruchom za pomocą ./cats:

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

Wyjaśnienie:

  • cat <<meowto składnia dokumentu tutaj . Nakazuje skryptowi pobranie bloku tekstu następującego po tej linii, dopóki nie napotka łańcucha meow. Zawartość zostanie następnie wyprowadzona (lub przesłana dalej).
  • >> catpotoki do pliku o nazwie cat.
  • Użycie >zamiast zamiast >>spowoduje zastąpienie pliku zamiast dołączenia do niego.
  • Meow!jest zawartością niniejszego dokumentu .
  • meowjest znacznikiem końcowym dla dokumentu tutaj . Zawartość jest, za pomocą >>, dołączana do cat.

Pipowanie zarówno do standardowego wejścia, jak i do pliku:

Aby wykonać instalację rurową, o którą prosisz, nie jest wymagany żaden dokument tutaj .

catnie może zarówno wyświetlać tekstu, jak i przekazywać go dalej, ale teeidealnie pasuje do tego, o co prosisz:

echo echo | tee tee

Spowoduje to wyświetlenie ciągu echoi zapisanie echodo pliku o nazwie tee.

Możesz również przekazać dane wyjściowe cat, jeśli jest to częścią wymagania, albo:

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

Lub tylko:

echo echo | tee tee | cat

Zawartość pliku:

$ cat tee
echo
Alexander
źródło
1
To tak naprawdę nie odpowiada na pytanie. Również >nie tworzy rur jako ostatnia kula implikuje.
strugee
2
@strugee, >może tworzyć potoki, zshgdy ten sam fd jest przekierowywany kilka razy, jak w echo foo >&1 > teelub echo foo > tee | cat, gdzie zshimplementuje wewnętrzny, teeaby podawać dane wyjściowe echozarówno catdo teepliku, jak i do pliku.
Stéphane Chazelas,
Zaktualizowałem moją odpowiedź, aby lepiej odpowiedzieć na pytanie.
Alexander