私が実行した場合:
cat messages.txt | sed -e 's/a/a/g' > messages.txt
大きなファイル(2500行以上)では、cygwinのコマンド以降に生成されたファイルには約900行しかありませんが、gentooでは行がないことがわかりました。しかし、私が走ったら
cat messages.txt | sed -e 's/a/a/g' > other_messages.txt
すべての行をそのままにしてください。
私の質問はなぜ
cat messages.txt | sed -e 's/a/a/g' > other_messages.txt
rm messages.txt
mv other_messages.txt messages.txt
答え1
ベルシュミットの答えsed を使用する場合に最適です。しかし、より一般的な意味では、次のようなアンチパターンがあります。
cat infile | filter > infile
多くの問題が発生する可能性があります。たとえば、次のファイルがあるとしますinfile
。
Hello
World
そして、次のコマンドを実行してください。
cat infile | tr "[:upper:]" "[:lower:]"
わかりました。
hello
world
ただし、実行すると空のcat infile | tr "[:upper:]" "[:lower:]" > infile
ファイルが表示されます。なぜ?
まあ、出力リダイレクト演算子を使用すると、>
「私の標準出力をこのファイルに入れ、ファイルが存在する場合は上書きされます」と言うことです。これでフィルタリングのためにこれがうまくいくはずだと思うかもしれません。コンパイラは元のすべての行を返します。ファイル。しかし、しばしば起こるのは、シェルが行を読み取る前にファイルを破損することです。その後、フィルタコマンドは空のファイルから行を読み込み、何も見つからないため、なしを返します。いくつかの場所では、ファイルが破損する前にいくつかの行を読むのに十分な「幸運」があるかもしれませんが、このパターンを完全に避けるのが最善です。
この特定の問題を解決するには、いくつかのオプションがあります。一つは、単に以下を行うことです。
cat infile | filter > tmpfile; mv tmpfile infile
一時ファイルが他のファイルを破損させたり、他の不快なことをしないようにする必要がある場合は、確認してください(およびmktemp
参照)。man mktemp
info coreutils mktemp
もう1つのオプションは、以下sponge
で使用することです。その他のユーティリティ。
さらに、これらの例の多くは猫に役に立たない用途。
答え2
ただ書くのはどうですか?
sed -i -e 's/a/a/g' messages.txt
-i は「所定の位置に」を意味します。
答え3
ファイルを適切に編集するもう1つの(移植可能な)方法はを使用することですed
。
# cf. http://wiki.bash-hackers.org/howto/edit-ed
cat <<-'EOF' | ed -s messages.txt
H
,g/a/s//b/g
wq
EOF
# ... or read the file contents into a variable, modify it and write it back to file
file_contents="$(cat messages.txt)"
printf '%s' "$file_contents" | sed -e 's/a/b/g' > messages.txt
# ... and, if you want to play around with a file descriptor hack, ...
# (As long as there's a fd associated with a file, the file can be accessed via the fd.)
exec 3<messages.txt # open file on fd 3 for reading
rm -f messages.txt
sed -e 's/a/b/g' <&3 > messages.txt
答え4
ExモードでVimを使用できます。
ex -sc '%s/OLD/NEW/g|x' messages.txt
%
すべての行を選択s
変えるg
グローバル交換x
保存して閉じる