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.