web-dev-qa-db-ja.com

ファイルから行を読み取って削除

ファイルから一連の行を読み取り、各行を削除するにはどうすればよいですか?

明らかに私はこのように読むことができます:

while read -r line; do
echo $line
done < myfile.txt

しかし、これを行うと:

while read -r line; do
echo $line
sed '1d' myfile.txt
done < myfile.txt

最初の行だけが表示されます

行を読み取るエレガントな方法を探し、それを使って何かを実行してから、ファイルの次の行に移動する前にそれを削除します。

6
DanF

sedを1回だけ呼び出してから、各行の反復で呼び出したいと思います。元のファイルを変更したい場合、sed-i-in-place)オプションを追加できます。

unset n
while read -r line; do
  echo $line
  : $((n++))
done < myfile.txt
sed "1,$n d" myfile.txt
2
Costas

できるよ:

sed -n '$d;w file2' >file1 <<IN
$(cat file1; echo .)
IN

これは、file1のすべての行を同時に削除しながら、file1からfile2にすべての行を安全に書き込みます。シェルは中間の一時ファイルを安全に処理します。1つのバイトを作成する前に、一時ファイルを作成してファイルシステムから削除します。

sedがファイル記述子を解放するとすぐ(at EOFまたはそれが終了したとき-どちらか早い方)ファイルは存在しなくなります。一般的なsed -iオプションとは異なり、これは、sed自体のクリーンアップに依存しません(処理が予期せず中断された場合は発生しない可能性があります)また、-iオプションが意味するのと同じアクセス許可の矛盾を伴いません。

そして、アプリケーションはデモンストレーションのようにグローバルである必要はありません-行を元の行から削除するか、別の出力に選択的に書き込むことができます...

sed -n '$d;/pattern1/w file2
           /pattern2/p' >file1 <<IN
$(cat file1; echo .)
IN

.../pattern2/に一致するfile1の行だけがfile1に出力される方法と、/pattern1/に一致する同じ行だけがwrittenからfile2に出力される方法を示します。もちろん、他のsedコマンドも同様に適用できます。

ただし、ほとんどのシェルでは、これがfile1からNULバイトを引き継がないことはおそらく注目に値します((sed work)の場合はあまり問題になりません)-このようなことはzshで可能です。

0
mikeserv

ファイルがこのスニペットで正しく処理されたら、ファイルのすべての行を置き換えることができます(処理が失敗した場合は削除しないでください。必要に応じて再処理できます)。

while read; do
  if some_command_worked_correctly; then
    sed -i '1,1 d' file-to-read
  fi
done < file-to-read
0
Diego Lago