ヒアドキュメントと猫と組み合わせて出力リダイレクトをどのように使用しますか?


56

別のコマンドにパイプする、またはファイルにリダイレクトする(sh例のためにパイプする)スクリプトがあるとしましょう。私はbashを使用していると仮定します。

私はそれを使用してそれを行うことができますecho

echo "touch somefile
echo foo > somefile" | sh

私もほとんど同じことをすることができますcat

cat << EOF
touch somefile
echo foo > somefile
EOF

しかし、「EOF」を「EOF | sh」に置き換えると、それは単にヒアドキュメントの一部であると考えるだけです。

cat標準入力からテキストを出力し、それを任意の場所にパイプで送るようにするにはどうすればよいですか?


touchそこにない限り、正確にあなたは何をしたいですか?入力ファイルを読み取り、stdoutで別のファイルにリダイレクトするだけですか?
ラーフルパティル

2
@RahulPatilもちろん無用です。ヒアドキュメントをわかりやすく説明するために、1行以上のサンプルが必要でした。そして、使用例を見てくださいecho-私はそれと同等のものが使用されるのだろうかと思いましたcat
-strugee

あなたの例はsh、複数の文字列からスクリプトを作成し、それを直接渡すことshです。HERE文書を含む複数のコマンドのテキスト出力を直接コマンドに渡すことを探しているQを見つけました。これがAshの答えの2番目の例です。
デイブX

回答:


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

複数のHereドキュメント

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

これにより、出力が生成されます。

hi
---
there

ここで何が起こっているのですか:

  • シェルは、( ... )サブシェルで囲まれたコマンドを参照して実行します。
  • 猫とエコーは非常に簡単です。インクルードは、cat <&3ファイル記述子を持つ猫を実行するように言う(FD)0(STDIN)FD 3からリダイレクト。つまり、fd 3からの入力を除外します。
  • (...)が開始される前に、シェルは2つのhereドキュメントのリダイレクトを確認し、fd 0(<<EOF)およびfd 3(3<<EOF2)をパイプの読み取り側に置き換えます
  • 初期コマンドが開始されると、シェルはEOFに達するまでそのstdinを読み取り、それを最初のパイプの書き込み側に送信します
  • 次に、EOF2と2番目のパイプの書き込み側で同じことを行います

最後から2番目の例を考えると、パイプの代わりにstdoutリダイレクトを使用した例を与えることができますか?
-strugee

リダイレクトの例を使用して回答を編集しました。これは編集したいフォームですか?そうでない場合、明確にするためにその部分の最初の行を与えることができますか?

1
シェルがこれをどのように処理するかを理解することが役立つ場合があります。コマンドラインを評価して<< EOFを見つけると、EOFのみの行が見つかるまで、または入力の終わりまで標準入力から読み取ります。元のコマンドラインでまだ処理されていない他のすべては、処理を続行します。そのため、たとえば、次のようなことを行うことができます。(cat; echo ---; exec <&3; cat) <<EOF 3<<EOF2 >out次に、2つのhere-blockを続けてそのコマンド入力を与えます。

シェル処理のあなたの説明は興味深いものでしたが、私の頭の上に:)私は何を知りたいと思ったことだろう何だった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、ここで文書の構文が。stringに遭遇するまで、この行に続くテキストブロックをピックアップするようにスクリプトに指示しますmeow。その後、コンテンツが出力されます(またはパイプされます)。
  • >> catという名前のファイルへのパイプcat
  • >代わりに使用すると>>、ファイルに追加する代わりに上書きされます。
  • Meow!here文書の内容です。
  • meowhereドキュメントの終了マーカーです。コンテンツは、を使用して>>、に追加され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
これは本当に質問に答えません。また>、最後の箇条書きが示すように、パイプを作成しません。
18年

2
@strugee、>内パイプを作成することができzsh、同じFDは同様に複数回リダイレクトされた場合echo foo >&1 > tee、またはecho foo > tee | cat、ここでzsh内部を実装するteeの出力供給するためechoの両方にcat、およびteeファイルを。
ステファンシャゼル

より良い質問に答えるように私の答えを更新しました。
アレクサンダー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.