非常に大きなファイル内の文字列の置換

非常に大きなファイル内の文字列の置換

区切り文字のない非常に長い一連の URL があり、形式は以下のとおりです。

http://example.comhttp://example.nethttp://example.orghttp://etc...

各 URL を新しい行にしたいのですが、sed を使用してすべての "http://" を "\nhttp://" に置き換えることでこれを実現しようとしました。

sed 's_http://_\nhttp://_g' urls.txt

しかし、セグメンテーション違反が発生します (メモリ違反)。ファイルのサイズが非常に大きい (100 GB を超える) ため、sed が何らかの制限を超えているとしか考えられません。

処理のためにファイルを複数の小さなファイルに分割することもできますが、「http://」のすべてのインスタンスはそのまま保持する必要があります。

これを行うより良い方法はありますか?

答え1

awk一度に大量のテキストを読む必要がなくなります:

awk -vRS='http://' -vORS='\nhttp://' 1 urls.txt > urlsperline.txt

成功するかどうかは、使用したawk実装によって異なる場合があります。たとえば、gawk正常に動作しますが、mawkクラッシュします。

答え2

これは役に立ちます:

perl -pe 'BEGIN { $/ = "//" } s!(?=http://\z)!\n!' urls.txt

設定することにより$/、行の定義を変更して、//改行ではなく で終わるようにしました。これにより、Perl は一度に 1 つの URL を読み取ります。URL に//スキームの後に except が含まれる可能性は低いですが、含まれていても問題ありません。正規表現により、不要な改行が追加されることはありません。

最初の URL の前に空白行を追加したくない場合は、次のようにします。

perl -pe 'BEGIN { $/ = "//"; print scalar <> } s!(?=http://\z)!\n!' urls.txt

ベンチマークを行って、より高速かどうか確認してみるのもよいでしょうs!http://\z!\nhttp://!。これらは同等です。/g置換ではフラグは不要であることに注意してください。これは、「行」ごとに 1 つの一致しか存在しないためです。

答え3

  1. :ファイルを分割するには、すべての a の出現を改行に変更します。
  2. 交換する
    • http行末に
    • 改行に続いてhttp:次の行を追加します
  3. 1回繰り返して、偶数行と奇数行を更新します

手順は次のようになります。

tr ':' '\n' | sed -e '/http$/{N;s/http\n/\nhttp:/}' | sed -e '/http$/{N;s/http\n/\nhttp:/}'
  1. で始まっていない行があるかどうかを確認しhttp://、行番号を出力します。これは、: が の後以外の URL のどこかにある場合にのみ発生しますhttp

    grep -nv '^http://'

関連情報