次のデータを含むファイルがありますlisting.txt
。
1
2
3
4
5
次に、次のコマンドを使用してファイルを繰り返し、各行で操作を実行します。
IFS=$'\n'
while IFS= read -r inc; do
if [ $inc -eq 1 ]
then
echo "FIRST: $inc"
else
echo "MID: $inc"
fi
done </home/user/listing.txt
しかし、最後の行であることを確認するオプションが見つかりません。私が最後の行にある場合、それを見つけるための最良の方法は何ですか?
私はループについて話している多くのページと、ファイルから最後の行を取得することについて話しているページを見ましたが、私のループがそれが最後の行にあることを知るのに役立つことはありません。
答え1
総行数とも呼ばれるファイルの最後の行番号を取得します。現在の行番号を追跡しながらファイルを繰り返します。現在の行番号が最後の行番号と同じ場合は、対処してください。
#!/bin/bash
file="some-file.txt"
last_line=$(wc -l < $file)
current_line=0
while read -r line; do
current_line=$(($current_line + 1))
if [[ $current_line -ne $last_line ]]; then
# is NOT last line
else
# IS last line
fi
done < $file
答え2
最後の行にあるとはどういう意味ですか?これは、この行の後に行がないことを意味するので、1つの戦略は、ループ内の現在の行の後に他の行があることを確認することです。そうでなければ最後の行にあり、そうでなければ真ん中にあります。
もう1つの手法は、ループの外側の変数に行を保持し、ループの終わりに変数に最後の行を含めることです。これは中間計算が不正確になるという欠点があるが、解決策を見つけることもできる。
答え3
WAFが説明で述べた内容を繰り返すには、それを使用してwc
ループの前の行数を取得してテストして、最後の行をキャプチャできます。
IFS=$'\n'
last=$(</home/user/listing.txt wc -l)
while IFS= read -r inc; do
if [ $inc -eq 1 ]
then
echo "FIRST: $inc"
elif [ $inc -eq $last ]
echo "LAST: $inc"
else
echo "MID: $inc"
fi
done </home/user/listing.txt
答え4
1つのオプションは、ループの一部を「解放」して、次の行の状態を使用して現在の行の処理を決定できるようにすることです。
{
IFS= read -r current
while IFS= read -r next; do
echo "MID: $current"
current=$next
done
echo "LAST: $current"
} </home/user/listing.txt
このようなループは行数やファイルの内容について何も知る必要はありません。特に、これはデータストリーム、つまり他のプロセスからパイプで接続されたデータと連携します(以下の例を参照)。
最初の行とは異なる操作を行うには、ループを少し広げます。
printf '%s\n' a b c d e | {
IFS= read -r first
echo "FIRST: $first"
IFS= read -r current
while IFS= read -r next; do
echo "MID: $current"
current=$next
done
echo "LAST: $current"
}
出力:
FIRST: a
MID: b
MID: c
MID: d
LAST: e