Come si usa il reindirizzamento dell'output in combinazione con qui-documenti e cat?


56

Diciamo che ho uno script che voglio reindirizzare a un altro comando o reindirizzare a un file (piping shper gli esempi). Supponiamo che sto usando bash.

Potrei farlo usando echo:

echo "touch somefile
echo foo > somefile" | sh

Potrei anche fare quasi la stessa cosa usando cat:

cat << EOF
touch somefile
echo foo > somefile
EOF

Ma se sostituisco "EOF" con "EOF | sh", penso solo che faccia parte dell'eredità.

Come posso farlo in modo che catemetta testo da stdin e quindi lo instrada in una posizione arbitraria?


toucha meno che non ci sia, cosa vuoi esattamente? è solo leggere il file di input e reindirizzare a un altro con stdout?
Rahul Patil,

2
@RahulPatil ovviamente è inutile. Volevo solo un esempio con più di una riga, per illustrare meglio l'ereditarietà. E guarda l'esempio usando echo- Mi chiedevo quale sarebbe stato l'equivalente di quello cat.
strugee,

Il tuo esempio è la creazione di uno shscript da più stringhe e il passaggio diretto a sh. Ho trovato la tua Q che cercava di passare l'output di testo di più comandi, incluso un documento HERE, direttamente a un comando. Questo è ciò che fa il secondo esempio della risposta di Ash.
Dave X,

Risposte:


91

Esistono diversi modi per farlo. Il più semplice è probabilmente questo:

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

Un altro, che secondo me è una sintassi migliore:

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

Anche questo funziona, ma senza la subshell:

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

Altre varianti:

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

O:

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

A proposito, mi aspetto che l'uso di catnella tua domanda sia un segnaposto per qualcos'altro. In caso contrario, eliminalo, in questo modo:

sh <<EOF
touch somefile
echo foo > somefile
EOF

Che potrebbe essere semplificato a questo:

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

o:

sh -c 'touch somefile
echo foo > somefile'

Reindirizzamento dell'output anziché delle tubazioni

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

Usando catper ottenere l'equivalente di echo test > out:

cat >out <<EOF
test
EOF

Più documenti qui

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

Questo produce l'output:

hi
---
there

Ecco cosa sta succedendo:

  • La shell vede ( ... )ed esegue i comandi racchiusi in una subshell.
  • Il gatto e l'eco sono abbastanza semplici. La cat <&3dice di correre gatto con descrittore di file (fd) 0 (stdin) Reindirizzamento da fd 3; in altre parole, elimina l'input da fd 3.
  • Prima di (...)iniziare, la shell vede i due documenti qui reindirizzare e sostituisce fd 0 ( <<EOF) e fd 3 ( 3<<EOF2) con il lato di lettura delle pipe
  • Una volta avviato il comando iniziale, la shell legge il suo stdin fino a quando non viene raggiunto EOF e lo invia al lato di scrittura della prima pipe
  • Quindi, fa lo stesso con EOF2 e il lato di scrittura della seconda pipe

dato il penultimo esempio, puoi fare un esempio con reindirizzamento stdout anziché piping?
strugee,

Ho modificato la risposta con un esempio di reindirizzamento; è questa la forma che volevi modificare? In caso contrario, puoi semplicemente dare la prima riga di quella parte per chiarire?
ash

1
Può aiutare a capire come la shell elabora questo. Quando sta valutando la riga di comando e trova << EOF, allora legge dall'input standard fino a quando non viene trovata una riga con solo EOF o la fine dell'input. Tutto il resto della riga di comando originale che non è stato ancora elaborato continua quindi a essere elaborato. Quindi, per esempio, è possibile fare qualcosa del genere: (cat; echo ---; exec <&3; cat) <<EOF 3<<EOF2 >oute quindi dare quell'input di comando con due blocchi qui di seguito.
ash

La tua spiegazione sull'elaborazione della shell è stata interessante ma sopra la mia testa :) Quello che volevo sapere era quale sarebbe stato l' catequivalente echo test > out, usando una eredità. Considerando che il tuo esempio dato ha aggiunto un reindirizzamento alla fine del tubo.
strugee,

1
@OlivierDulac - Ho aggiunto l'esempio di eredità multipla alla risposta.
ash

1

Voglio solo sottolineare che l'utilizzo meowè valido quanto EOF.

Questo script verrà aggiunto Meow!a un file denominato cat:

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

Salva con nome catse rendilo eseguibile con chmod +x cats, quindi eseguilo con ./cats:

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

Spiegazione:

  • cat <<meowè la sintassi del documento qui . Indica allo script di raccogliere il blocco di testo che segue questa riga, fino a quando non incontra la stringa meow. Il contenuto verrà quindi emesso (o convogliato insieme).
  • >> catpipe al file denominato cat.
  • Usando >invece di >>sovrascriveresti il ​​file invece di aggiungerlo ad esso.
  • Meow!è il contenuto del documento qui .
  • meowè il marker di fine per il documento qui . I contenuti sono, con l'uso di >>, aggiunti cat.

Piping sia su stdout che su un file:

Per eseguire le tubazioni richieste, non è richiesto alcun documento qui .

catnon è in grado di emettere testo e trasmettere il testo, ma teeè una corrispondenza perfetta per quello che stai chiedendo:

echo echo | tee tee

Ciò genererà sia la stringa echoche la scrittura echoin un file denominato tee.

È inoltre possibile trasmettere l'output cat, se fa parte del requisito, con:

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

O semplicemente:

echo echo | tee tee | cat

Contenuto del file:

$ cat tee
echo

1
Questo non risponde davvero alla domanda. Inoltre >, non crea pipe come implica l'ultimo proiettile.
Strugee,

2
@strugee, >può creare pipe zshquando lo stesso fd viene reindirizzato più volte come in echo foo >&1 > teeo echo foo > tee | cat, dove zshimplementa un interno teeper alimentare l'output di echoentrambi cate del teefile.
Stéphane Chazelas,

Aggiornato la mia risposta per rispondere meglio alla domanda.
Alexander
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.