web-dev-qa-db-ja.com

出力をshスクリプトにパイプし、それをコマンドにパイプする方法は?

私はこれをグーグルで検索して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

次とまったく同じように動作します。

myscript:

#!/usr/bin/env sh
gzip

catファイル| ./myscript

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

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

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

2
vrijdenker
#!/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から削除します。

3
Kusalananda

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

そうは言っても、これはあなたの質問が尋ねることをします:

#!/bin/sh
gzip "$@"
2
roaima

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
1