Bash文は何をしますか?

Bash文は何をしますか?

次のステートメントが何をしているのか私に説明できますか?

grep `date +%Y-%m-%d --date='1 day ago'` /path/to/file/FILE_PREFIX_\`date +%Y%m%d --date='1 day ago'`.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

答え1

次のファイルがあるとしましょう。

$ cat path/to/file/FILE_PREFIX_20150730.dsv
2015-07-29|0100
2015-07-30|0200
2015-07-30|0300
2015-07-31|0400

次に、(少し固定された)コマンドが実行する操作を見てください。

$ grep `date +%Y-%m-%d --date='1 day ago'` path/to/file/FILE_PREFIX_`date +%Y%m%d --date='1 day ago'`.dsv  | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'
27200
27300

簡単に言えば、名前が昨日の日付に基づいているファイルを見て、そのファイルの形式で昨日のpath/to/file/FILE_PREFIX_20150730.dsv日付を参照するすべての行を見つけます2015-07-30。その後、文字も含まれているすべての行を削除しますERROR。残りの行は文字に基づいてフィールドで区切られます|。行の2番目のフィールドを抽出します。 2番目のフィールドが0で始まる場合、0は置き換えられます27

答え2

まず第一に、あなたが提供するものは文ではありません。これは、次のように接続された一連のコマンドです。管路そしてコマンドの置き換え

grep `date +%Y-%m-%d --date='1 day ago'` /path/to/file/FILE_PREFIX_\`date +%Y%m%d --date='1 day ago'`.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

一つずつ分解してみましょう。

コマンドの置き換え

  • date +%Y-%m-%d --date='1 day ago'2回発生し、昨日の日付をフォーマットYYYY-mm-dd(例:2015-07-31)で提供します。
    • 2番目の呼び出し(pathnameの呼び出し)は、フォーマットを次のように調整します。YYYYmmdd
    • それを作るためにバックティックに入れてコマンドの置き換え。これは$(date +%Y-%m-%d --date='1 day ago')、ネストを許可し、エスケープの面であまり面倒でない後者(および最新の)形式を入力することによって得られるのと同じ効果です。

効果コマンドの置き換えコマンドラインから次のようなものを割り当てます。

YESTERDAY1=$(date +%Y-%m-%d --date='1 day ago')
YESTERDAY2=$(date +%Y%m%d --date='1 day ago')

次に、コマンドラインを次のように書き直します。

grep $YESTERDAY1 /path/to/file/FILE_PREFIX_$YESTERDAY2.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

パイプで接続された個々のコンポーネント

  • grep $YESTERDAY1 /path/to/file/FILE_PREFIX_$YESTERDAY2.dsvgrepは、ファイル内の昨日の日付値を見つけて/path/to/file/FILE_PREFIX_$YESTERDAY2.dsv出力しますstdout(参照:標準ストリーム)
  • grep -v 'ERROR'すべてをgrepその他ERROR入力に対してこれを行い、stdinにも書き込みますstdout
  • cut -d "|" -f 2入力行(stdin)がパイプ文字で区切られているとし(-d "|"ここでパイプ文字が文字列にどのように表示されるかを確認してください)、2番目のフィールド(-f 2)を選択して作成しますstdout
  • sed 's/^0/27/'()(元の入力の2番目のフィールドを覚えています)で、s/.../.../0で始まるすべての文字列を27に置き換えて作成します。stdin^stdout

管路

文字列の外側に現れるパイプ文字、つまり単一文字を除くすべての文字は、前のコマンドをcut -d "|" -f 2次のコマンドにリンクします。stdoutstdin

これにより、最初の読み取りファイルの出力がgrep2番目の読み取りファイルgrepの出力に移動されます。

これはUnix哲学の原則に従います。「一つのことを上手にしなさい」

それらを一つにまとめる

私の説明ではこの変数を使用YESTERDAY1し、YESTERDAY2コマンド置換セクションで説明しました。今理解できるでしょう。

しかし、一つのことがあります。これが真実かどうか疑問ですが、真夜中の非常に遅いシステムでは、これら2つのコマンド置換を実行するまでの時間が、必要なものとはgrep異なるファイル名の値を生成するのに十分な長さになる可能性があります。

ちなみに

本当に複雑になり、昨日の値が異なる可能性がある問題を回避したい場合は、次のようにします。パラメータ拡張${parameter/pattern/string})それはすべてです。まず、日付を変数に入れます。コマンドの置き換え:

YESTERDAY=$(date +%Y-%m-%d --date='1 day ago')

その後、使用パラメータ拡張次のように、変数の1つのインスタンスからダッシュを削除します。

grep $YESTERDAY /path/to/file/FILE_PREFIX_${YESTERDAY//-}.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

これにより、日付値を一度だけ検索することができます(ただし、タイムアウトしますが)、他の日付を取得する可能性はありません。

おすすめブック

関連情報