web-dev-qa-db-ja.com

Bashでユーティリティプログラムへの連鎖呼び出しをパラメーター化する

Stdinからデータの列を読み取り、それらを処理(スムージング効果を適用)してからstdoutに出力するブラックボックスUNIXプログラムをBashシェルで使用しています。私は、UNIXパイプで使用します。

generate | smooth | plot  

より平滑化するために、平滑化を繰り返すことができるため、Bashコマンドラインから次のように呼び出すことができます。

generate | smooth | smooth | plot   

あるいは

generate | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | plot

これは不穏になっています。 Bashラッパーをsmoothにパイプして、その出力をsmoothの新しいインスタンスに任意の回数だけフィードバックできるようにしたいと思います。

generate | newsmooth 5 | plot

の代わりに

generate | smooth | smooth | smooth | smooth | smooth | plot

最初の試みは、現在のディレクトリに一時ファイルを生成して削除するBashスクリプトでしたが、書き込みアクセス権のあるディレクトリにいない場合は醜くなり、中断されたときにガベージファイルも残されました。

smoothプログラムには引数はありません。

そのようなプログラムを「ラップ」して呼び出しの数をパラメーター化するよりエレガントな方法はありますか?

12
Diane Wilbor

あなたはそれを再帰的な関数でラップすることができます:

smooth() {
  if [[ $1 -gt 1 ]]; then # add another call to function
    command smooth | smooth $(($1 - 1)) 
  else
    command smooth # no further 
  fi
}

これを次のように使用します

generate | smooth 5 | plot

これは

generate | smooth | smooth | smooth | smooth | smooth | plot
18
muru

必要なsmoothコマンドの数と同じ数のコンマを入力できる場合は、シェルのコンマ区切りの大括弧拡張を利用できます。

TL; DR

サンプルケースのコマンドライン全体は次のようになります。

generate | eval 'smooth |'{,,,,} plot

注意:

  • smooth |の繰り返しを増やしたり減らしたりする場合は、カンマを追加または削除します
  • plotの前に|はありません。これは、ブレース拡張によって生成された最後のsmooth |文字列に含まれているためです。
  • smoothに引数を指定することもできますが、開き括弧の前にある引用符で囲まれた固定部分に引数を正しく含めることができます。いずれの場合も、コマンドのall繰り返しにそれらを提供することを覚えておいてください

仕組み

カンマで区切られたブレース展開を使用すると、指定された固定部分と指定された可変部分で構成される文字列を動的に生成できます。 a{b,c,d}ab ac adを生成するように、指定された変数部分と同じ数の文字列を生成します。

ここでの小さなトリックは、empty変数部分のリストを作成する場合、つまり中括弧内にコンマのみを使用する場合、ブレース拡張は単にコピーを生成するということです固定部分のみ。例えば:

smooth{,,,,}

生成されます:

smooth smooth smooth smooth smooth

4コンマは5つのsmooth文字列を生成することに注意してください。これが、このブレース拡張のしくみです。コンマに1を加えた数の文字列を生成します。

もちろん、あなたのケースでは各smoothを区切る|も必要なので、固定部分に追加するだけですが、適切に引用してシェルnotはそれをすぐに解釈します。あれは:

'smooth|'{,,,,}

生成されます:

'smooth|' 'smooth|' 'smooth|' 'smooth|' 'smooth|'

常に、固定部品をすぐに開きブレースに隣接して配置するように注意してください。つまり、'{の間にスペースを入れないでください。 。

(固定部分でシェル変数を展開する必要がある場合は、固定部分を形成するために、単一引用符の代わりに二重引用符を使用することもできます。余分なエスケープに注意してくださいシェルの特殊文字が二重引用符で囲まれた文字列の中にある場合に必要です。

この時点で、シェルに最終的にパイプラインコマンドとして解釈させるために、その文字列にevalを適用する必要があります。

したがって、すべてをまとめると、サンプルケースのコマンドライン全体は次のようになります。

generate | eval 'smooth |'{,,,,} plot
5
LL3