
返される文字列に割り当てられた変数があります:
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/')
tail
GNU では省略できます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
を組み合わせて、を使用できます。cat
grep
sed
tail
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 }
これはファイルの各行に順番に適用されます。現在の行に一致する年がある場合は、それを変数に保存しますawk
。line
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 文字のみを出力します。