コマンドとパラメータを分割してbashスクリプトの変数に入れます。

コマンドとパラメータを分割してbashスクリプトの変数に入れます。

grep同じ(非常に長い)コマンドを複数回繰り返すスクリプトがあります。行の長さを短くしてスクリプトを読みやすくしたいので、命令の一部を変数に入れました。

次の行は次のとおりです(他のパラメータを使用してスクリプトで複数回繰り返されます)。

rsync -av --delete -R --exclude=alternatives /etc/ /backup.raw/ | grep -E '^deleting|[^/]$' >> /var/log/rsync.log

その行はうまくいきます。私はそれを次のように短縮してみました。

_rscmd='rsync -av --delete -R'
_mn=/backup.raw/
_grep='grep -E "^deleting|[^/]$"'
_rslog=/var/log/rsync.log

したがって、「最後の」行は次のようになります。

$_rscmd --exclude=alternatives /etc/ $_mn | $_grep >> $_rslog

しかし、その行は$_grep変数で失敗します。どうすれば正しく書くことができますか?私は成功"…"しませ'…'んでした。 grepコマンドはもともと機能しました。

答え1

変数を使用している場合は、複数の部分(コマンドとパラメータ)に分割することは機能しません。この例の場合eval:

eval $_rscmd --exclude=alternatives /etc/ $_mn | eval $_grep >> "$_rslog"

一般的に使用するのが最善です。シェル機能またはニックネーム 変数を使用するよりも:

alias my_grep='grep -E "^deleting|[^/]$"'
...
... | my_grep >> "$_rslog"

答え2

一般的なアプローチは、コマンドのパラメータを変数に設定することです。

_mn=/backup.raw/
_rscmdarg='-av --delete -R'
_greparg='-E "^deleting|[^/]$"'
_rslog=/var/log/rsync.log

$_rslogファイルやディレクトリと同じように$_mnアーカイブしても大丈夫です。

「最後の」行は次のとおりです。

rsync $_rscmdarg --exclude=alternatives /etc/ $_mn | grep  $_greparg >> $_rslog

答え3

他の2つの答えの最良の部分を統合する1つの方法(IMHO)は、変更せずに必要なすべての機能を含め、さまざまな状況で変化する機能を指定する引数を使用するシェル関数を作成することです。例:

my_rsync_grep() {
      rsync -av --delete -R "$1" "$2" "$3" | grep -E '^deleting|[^/]$' >> /var/log/rsync.log
}

必須パラメータを使用して呼び出します。

my_rsync_grep --exclude=alternatives /etc/ /backup.raw/

rsync … | grep …これはコマンドを別のスクリプトに入れたのと同じです。 (ただし、別々のファイルではないため、複数のファイルを追跡する構成管理の問題や他のスクリプトを呼び出す方法に関する論理的な問題(例:?を使用しますか?)がなく、関数を毎回./呼び出すことはありません。追加のディスクI / Oは発生しません。)

メモ:

  • 読みやすさとプログラミングスタイルの理由から、I / Oリダイレクト(>> /var/log/rsync.log)を関数から移動してすべての呼び出しに適用できます。

    my_rsync_grep --exclude=alternatives /etc/ /backup.raw/ >> /var/log/rsync.log
    

    これにより、スクリプトを読んだり保守したりする人に、その行がファイルに書き込まれていることが明らかになります。しかし、スクリプトに誤って矛盾が発生しやすくなります。もちろん、ファイル名を変数(たとえば)に入れることで、1行を$_rslog減らすことができます/var/log/rsycn.log

  • 1行が長すぎて関数コードの読みやすさが低下したと思われる場合は、複数行に分けることができます。\最後の行を除くすべての行に1つを追加します。

          rsync -av --delete -R "$1" "$2" "$3" | grep -E \
                  '^deleting|[^/]$' >> /var/log/rsync.log
    

    |特別な場合で、&&直後に中断する||場合は\オプションです。または:

          rsync -av --delete -R "$1" "$2" "$3" |
                grep -E '^deleting|[^/]$' >> /var/log/rsync.log
    
  • 前述のように、この関数は常に3つの引数で呼び出されると仮定します。この仮定は非現実的なようです。コマンドを実行しrsyncてすべての引数を関数に渡すには、次のようにします"$@"

          rsync -av --delete -R "$@" | grep …
    
  • grepたとえば、引数を引数として使用するように関数を変更したい場合

    my_rsync_grep --exclude=代替/etc//backup.raw/(他のパラメータ)「^削除| [^ /] $」

    次のことができます。

    my_rsync_grep() {
          nargs=$(($#-1))
          rsync -av --delete -R "${@:1:nargs}" | grep -E "${@:$#}" >> /var/log/rsync.log
    }
    

    よりパラメータ拡張部分大きな打撃(1)$@などの構文に関する追加情報。${parameter:offset:length}

    注:この構文はで動作しない可能性がありますbash

関連情報