出力を sh スクリプトにパイプし、それをコマンドにパイプするにはどうすればよいでしょうか?

出力を sh スクリプトにパイプし、それをコマンドにパイプするにはどうすればよいでしょうか?

私はこれについて Google で検索し、Stack を検索しましたが、まさにやりたいことが見つかりませんでした。まだこのことを理解できていません。

たとえば、gzip のラッパーにすぎない sh スクリプトがあるとします (単なる例)。コマンドラインで、何か (たとえばmysqldump) の出力をスクリプトにパイプします。そのスクリプトは入力を受け取り、それを gzip にパイプする必要があります。

コマンドラインの例:

mysqldump somedb | myscript > somefile.dmp.gz

myscript の例 (私が試したもの):

#!/usr/bin/env sh
read inp
command="echo \"$inp\" | gzip"
eval $command

おそらくこの例では多くの点が間違っています。助けてください。:)

解決策(それを探している人向け)

以下の説明のおかげで、SH スクリプトでコマンドを実行すると、コマンドが直接実行された場合と同じように、入力がスクリプトにパイプされるだけであることが分かりました。

この場合は次のようになります。

cat ファイル | gzip

次のようにすると、まったく同じ動作になります。

マイスクリプト:

#!/usr/bin/env sh
gzip

cat ファイル | ./myscript

したがって、私の場合には別の問題もあったことを指摘したいと思います。実際のスクリプトでは、次のように読み取って入力ストリームがあるかどうかを確認しようとしました。

read inp
if [ -z "$inp" ]; then
    echo "No input"
    exit;
fi

read inpの後、入力パイプは空であることがわかります。

答え1

#!/bin/sh
gzip -c

それで十分でしょう。

$ mysqldump ... | ./script >out.gz

gzip -c標準入力から非圧縮データを読み取り、標準出力に圧縮データを書き込みます。

標準入力はパイプによって提供され、標準出力はファイルにリダイレクトされます。パイプとリダイレクトは、呼び出し元のシェルによって処理されます。

sedコマンドラインで式を受け取り、それに従って入力を変換するか、式が使用されなかった場合はデータを転送するだけの、もう少し複雑な例です。

#!/bin/sh

if [ -n "$1" ]; then
    sed -e "$1"
else
    cat
fi

(ここで を使用するとsed -e ""と同じ効果が得られますcatが、より複雑な例が欲しかったのです)

$ utility | ./script "1,5d" >out

... は、出力の最初の 5 行を削除しますutility

答え2

複雑な状況をより単純な例で説明しようとしているため、スクリプトのどの部分が単純な誤解で、どの部分が複雑なのかわかりません。

そうは言っても、これはあなたの質問が求めていることを実行します:

#!/bin/sh
gzip "$@"

答え3

を使用し、入力の一部を読み取って空かどうかを確認するには、次のように変数に任意のバイト値を格納できるようreadなシェルを使用する必要があります。zsh

#! /bin/zsh -
if LC_ALL=C read -ru0 -k1 byte; then
  # one byte was read, the input is not empty
  (printf %s "$byte"; cat) | gzip
else
  echo >&2 No input
fi

または、何らかの形式のエンコードを使用します。

#! /bin/sh -
# get the value of the first byte as octal:
byte=$(od -An -N1 -vto1 | tr -cd 0-7)

if [ -n "$byte" ]; then
  (printf "\\$byte"; cat) | gzip
else
  echo >&2 No input
fi

関連情報