変数の置換

変数の置換

返される文字列に割り当てられた変数があります:

ytd_wk=$(cat file.csv | grep $(date +'%Y') | tail -1)

最後の 2 文字を部分文字列化したい:

ytd_wk=${ytd_wk:(-2)}

これを実現するためにワンライナーを使用する方法はありますか? 以下を試しましたが、bad substitutionエラーが発生しました:

ytd_wk=${$(cat file.csv | grep $(date +'%Y') | tail -1):(-2)}

答え1

以下をお試しください:

grep "$(date +'%Y')" file.csv | tail -1 | sed 's/.*\(..$\)/\1/'

cat別のプログラムの出力または特定のファイルからデータを取得できるため、必要ありませんgrep。最後の方法は、1 つのコマンドのみを使用するため、より効率的であり、より高速で、消費するシステム リソースが少なくなります。

完全なソリューション:

ytd_wk=$(grep "$(date +'%Y')" file.csv | tail -1 | sed 's/.*\(..$\)/\1/')

tailGNU では省略できますsed '$!d':

grep "$(date +'%Y')" file.csv | sed -r '$!d;s/.*(..$)/\1/'

POSIX:

grep "$(date +'%Y')" file.csv | sed -e '$!d' -e 's/.*\(..$\)/\1/'

答え2

他の提案の、、、およびawkを組み合わせて、を使用できます。catgrepsedtail

awk -v year=$(date +'%Y') '$0 ~ year {line=$0} END {print substr(line,length(line)-1,2)}' file.csv

これを段階的に書き出すと

  • -v year=$(date +'%Y')awk変数をyear現在の年に設定します
  • $0 ~ year { line=$0 }これはファイルの各行に順番に適用されます。現在の行に一致する年がある場合は、それを変数に保存しますawkline
  • END { print substr(line,length(line)-1,2) }ファイルの最後 (最後の行が読み込まれて処理された後) に、最後に保存された行の最後の 2 文字を出力します。以前に一致が見つからなかった場合は、空白行を出力します。

答え3

これは、特に次のような場合に効果的です。ファイル.csvが大きく、目的の行が末尾に近い場合:

ytd_wk="$(tac file.csv | grep -m 1 $(date +'%Y') | grep -o '..$')"

仕組み: tac出力ファイル.csv逆方向に進み、grep -m 1パターンの最初のインスタンスを見つけます。このインスタンスは、grep -o最後の 2 文字のみを出力します。

関連情報