巨大なファイル内の改行を含む文字列を置換する

巨大なファイル内の改行を含む文字列を置換する

ある程度メモリ効率の良い方法で文字列を「バイナリ」検索/置換する非行ベースのツールを知っている人はいますか?見るこの質問あまりにも。

2GB 以上のテキスト ファイルがあり、次のように処理したいと考えています。

sed -e 's/>\n/>/g'

つまり、 の後に発生するすべての改行を削除したいのです>が、それ以外の場所では削除したくないので、 は除外されますtr -d

このコマンド(私が同様の質問の答え) は失敗しますcouldn't re-allocate memory:

sed --unbuffered ':a;N;$!ba;s/>\n/>/g'

では、C に頼らない他の方法はあるのでしょうか? 私は Perl が嫌いですが、この場合は例外を認めるつもりです :-)

データに存在しない文字があるかどうかはわかりませんので、一時的に\n別の文字に置き換えることは、できれば避けたいものです。

何か良いアイデアはありますか?

答え1

これは Perl では本当に些細なことなので、嫌いになる必要はありません。

perl -i.bak -pe 's/>\n/>/' file

説明

  • -i: ファイルをその場で編集し、 というオリジナルのバックアップを作成しますfile.bak。バックアップが必要ない場合は、代わりに を使用しますperl -i -pe
  • -pe: 入力ファイルを行ごとに読み取り、指定されたスクリプトを適用した後、各行を出力します-e
  • s/>\n/>/: と同様に置換されますsed

ここでawkアプローチを紹介します:

awk  '{if(/>$/){printf "%s",$0}else{print}}' file2 

答え2

解決策perl

$ perl -pe 's/(?<=>)\n//'

説明

  • s///文字列の置換に使用されます。
  • (?<=>)後読みパターンです。
  • \n改行に一致します。

パターン全体は、>その前にあるすべての改行を削除することを意味します。

答え3

これはどう:

sed ':loop
  />$/ { N
    s/\n//
    b loop
  }' file

GNU sed の場合、質問に従って-u( ) オプションを追加することもできます。GNU sed は、これを単純なワンライナーとして受け入れます。--unbuffered

sed ':loop />$/ { N; s/\n//; b loop }' file

答え4

sedは、最後の改行なしで出力を生成する方法を提供していません。 を使用したアプローチはN基本的に機能しますが、不完全な行をメモリに保存するため、行が長くなりすぎると失敗する可能性があります (sed の実装は通常、極端に長い行を処理するようには設計されていません)。

代わりに awk を使用することもできます。

awk '{if (/<$/) printf "%s", $0; else print}'

別の方法としては、 を使ってtr改行文字を「退屈な」頻繁に出現する文字と交換する方法があります。スペースはここで機能するかもしれません。データ内のすべての行、または少なくとも大部分の行に出現する傾向がある文字を選択してください。

tr ' \n' '\n ' | sed 's/> />/g' | tr '\n ' ' \n'

関連情報