Bash - テキスト ファイル全体を読み取らずに、ファイルの先頭に文字列を追加するにはどうすればよいでしょうか?

Bash - テキスト ファイル全体を読み取らずに、ファイルの先頭に文字列を追加するにはどうすればよいでしょうか?

「test.txt」というテキスト ファイルの前に文字列「hello world」を挿入しようとしています。これはすでに sed で実行していますが、残念ながら「sed コマンド」はファイル全体を読み取るため、メモリを使い果たしてしまいます。

ファイルには 1 GB サイズのテキストが含まれていますが、メモリは 512 MB しかありません。どうすればいいでしょうか? たとえば次のようになります:

echo --insert-before "hello world" >> test.txt

または、前に挿入するためにどの演算子を使用する必要がありますか。次のようになります。

echo "hello world" << test.txt

それとも別のアイデアですか?

注: 最後にテキストを挿入する演算子は>>正常に機能し、メモリを消費しませんが、テキスト ファイルの内容を上書きせず、改行せずに、ファイルの先頭に対して逆の操作を行う必要があります。

私が実際に使用したコードは次のとおりです:

echo "hello world" > test.txt;
echo "the large content that size is 1gb" >> test.txt;
sed -i ':a;N;$!ba;s/\n//g' test.txt;

答え1

使用したコマンドのシーケンスは次のとおりであると述べています:

echo "hello world" > test.txt;
echo "the large content that size is 1gb" >> test.txt;
sed -i ':a;N;$!ba;s/\n//g' test.txt;

実際のコマンドは次のとおりであると仮定します。

echo "hello world" > newfile;
cat test.txt >> newfile;            # assuming the file with 1GigaByte was test.txt

そして、あなたは sed コマンドについて不満を述べていますが、これは改行を削除するためだけにあります (あなたの説明から)。

trメモリをあまり使用しないで同じことを行うことができます。

echo "hello world" > newfile;
cat test.txt | tr -d '\n' >> newfile

そして、newfile先頭に「hello world」が追加された test.txt のコピーが作成されます。

答え2

sedメモリをあまり使用しません。ただし、OS がディスクをキャッシュしている可能性があります。したがって、 を使用するとnocache役立つ場合があります (ディスクが十分に高速であるか、同じデータを複数回読み取っていない場合)。また、--unbufferedのオプションを使用しますsed(これにより、sedはメモリをできるだけ少なく使用します)。

>>また、コマンドではなくシェルによって実行されるecho オプションも存在しません。これは、コマンドの stdout をファイルに追加するようにシェルに指示します。

@Kusalananda が言うように、あなたのsedスクリプトは効率的ではありません。おそらく cat を使うだけでしょう。

uncache cat "<(echo the_prefix)" old_file_name > new_file_name
rm old_file_name
mv -T new_file_name old_file_name #note not all `mv`s have the `-T` option, it can unsafely be left out.

答え3

もう少しシンプルなものはいかがでしょうか?

cat <<_eof_ > file
Hello world!
$(cat file)
_eof_

またはedを使用する

echo '0a
your text here
.
w' | ed some_file

答え4

これがあなたの記憶を殺している場合:

sed -i ':a;N;$!ba;s/\n//g' "test.txt"

次に、改行を削除して一度に 1 行だけ読み取るには、次のようにします。

{
    printf "hello world"  # with no newline
    while IFS= read -r line || [ -n "$line" ]; do
        printf "%s" "$line"
    done < test.txt
    echo ""          # add a newline to the end of the file
} > test.txt.tmp && mv test.txt{.tmp,}

通常の状況では、これは sed よりも少し遅くなりますが、あなたの状況は異常です。

関連情報