direction
次の行を含むファイルがあるとします。
east
north
south
west
south-west
ループを使用し、echo
シェルスクリプトから次の出力を生成します。
Direction: east
Direction: north
Direction: south
Direction: west
Last direction: south-west
つまり、スクリプトの最後の行で別の操作を実行したいと思います。
答え1
bash
ファイルの終わりを検出する方法はありませんが(次の行を読み取ろうとせずに失敗します)、Perlはそのeof
機能を使用できます。
$ perl -n -e 'print "Last " if eof; print "Direction: $_"' direction
Direction: east
Direction: north
Direction: south
Direction: west
Last Direction: south-west
注:echo
Bashとは異なり、Perlのステートメントは1.印刷する文字列に含めて明示的に指定するか、2. Perlのコマンドラインオプションを使用するか、3.文字列に新しい行を含める場合を除きprint
、改行を印刷しません。 - の場合なので改行文字を削除するのによく必要です。\n
-l
$_
chomp()
Perlでは、BTWは$_
現在の入力ラインです。あるいは、実際の変数名を指定しないループの基本イテレータ(しばしば「現在のエントリ」と呼ばれます)たくさん$_
指定しない場合、Perl関数と演算子はデフォルト/暗黙のパラメータとして使用されます。表示man perlvar
と検索$_
sed
また動作します。$
アドレスはファイルの最後の行と一致します。
$ sed -e 's/^/Direction: /; $s/^/Last /' direction
Direction: east
Direction: north
Direction: south
Direction: west
Last Direction: south-west
ルールの順序がsed
重要です。私の最初の試みは間違った方向に進みました(そして「方向:最後の南西」が印刷されました)。この sed スクリプトは常に各行の先頭に "Direction:" を追加します。最後の行($
)では、前のステートメントによって変更された行の先頭に「Last」を追加します。
答え2
ループは、実際に終わりに達しない限り、いつ終わりに到達したかを知りません。したがって、ファイルを2回処理します。 1回は行数を取得し、もう1回は出力を処理するか、各反復で前の値を印刷し、ループを終了したときに最後の値を印刷します。
prev=""
while read direction; do
if [ -n "$prev" ]; then
echo "Direction: $prev"
fi
prev="$direction"
done < direction
echo "Last Direction: $prev"
答え3
の変種FelixJNの答え、行を配列として読み込みますが、bashループの代わりにbash組み込みを使用します。
mapfile -t DIR < direction
printf "Direction: %s\n" "${DIR[@]::${#DIR[@]}-1}"
printf "Last direction: %s\n" "${DIR[-1]}"
マップファイル標準入力を項目ごとに1行ずつ配列として読み取るBash 4に追加された組み込み関数。この-t
オプションは改行文字を削除します。
printf
そのフォーマット文字列は、すべての入力パラメータが使い果たされるまで繰り返し適用されます。
答え4
paste
、tail
および次のものを混在させることができますhead
。
$ paste -s -d'\n' <(head -n -1 direction | sed 's/^/Direction: /') <(tail -n1 direction | sed 's/^/Last direction: /')
Direction: east
Direction: north
Direction: south
Direction: west
Last direction: south-west
paste -s -d'\n'
-d'\n'
オプションとオプションとともに、改行文字を区切り文字として使用します-s
。-s、--
serial並列ではなく一度に1つのファイルを貼り付けます。head -n -1
最後の行とパイプを除くすべての行を検索し、その行sed
にのみ必要なコマンドを実行します。tail -n1 file
ファイルの最後の行を検索してパイプし、その行sed
に必要なコマンドのみを実行します。
またはより簡潔にcat
代わりに使用してくださいpaste
。@MickMatteoによるコメント:
$ cat <(head -n -1 direction | sed 's/^/Direction: /') <(tail -n1 direction | sed 's/^/Last direction: /')