パターンで区切られた連続行グループを結合する技術

パターンで区切られた連続行グループを結合する技術

次のリストがあります。

$$<002L_tbfl
Putative transcription factor 001R;
GO:0006355
GO:0046782
GO:0006351
IPR007031
$$<002L_FRG3G
Uncharacterized protein 002L;
GO:0033644
GO:0016021
IPR004251

私はそれぞれが新しい行を開始して再び表示される$$<まで、同じ行(タブで区切られた)に次の項目を持たせたいと思います。$$<このように:

$$<002L_tbfl    Putative transcription factor 001R; GO:0006355  GO:0046782  GO:0006351  IPR007031
$$<002L_FRG3G   Uncharacterized protein 002L;   GO:0033644  GO:0016021  IPR004251

これまでの私のアプローチは次のとおりです。

tr '\n' '\t'   < stage1 > stage2
sed 's/$$</\n/g' stage2 > stage3

問題は、上記の方法が小さなファイルでは完全に機能しますが、4 GBファイルでは機能しているように見える次の短い時間にエラーやメッセージなしで空のファイルを返すことです。
私も試してみましたが、tr '$$<' '\n'うまくいきません。奇妙なファイルが生成されます。

答え1

実行方法は次のとおりですsed

sed -n '/$$</! H; /$$</{x; s/\n/\t/gp}; ${x; s/\n/\t/gp}' stage1 > stage3

部分に分かれています:

  • sed -nデフォルト出力(つまり、処理された入力)が印刷されず、pコマンドを受け取った場合にのみ印刷されることを意味します。
  • /$$</! H線が見える時を意味します。いいえ含まれている場合は$$<「に追加してください。時間前のスペース"(たとえば、準備領域)。これは、一般的なロジックを反転して、"この条件を満たさない行に対してこれを実行することを!意味します。$$<(および(たとえば、行の前に改行を挿入するなどの行の途中を別々に処理する必要がある/^$$</場合は、それを記録するように質問を編集してください。)$$<

    予約済みスペース(予約済みスペース)に既にコンテンツがある場合予約済みスペースに行を追加する場合、その間sedに改行文字を挿入すると、予約済みスペースに次のテキストが作成されます。

    $$<002L_tbflnewline推定転写因子001Rnewline移動:0006355…

    スペースを「パターンスペース」(通常の作業行バッファー)として予約 一般的に言えば最後に明示的な改行文字はありません(暗黙的です)。もちろん、スペース内に明示的に改行文字を挿入できます。

  • /$$</{…}中かっこで囲まれたコマンドを含む行で実行されることを示します$$<

    • xeを意味するX予約済みスペースとパターンスペースの内容を変更します。
    • s/\n/\t/gp意味 - まあ、当然のことです、そうですか? - これは(パターンスペースで)改行文字をタブに置き換えることを意味します。 G世界中で結果を印刷します。

    このコマンドが入力の最初の行(を含む$$<)を読み取ると、xその行($$<002L_tbfl)をパターンスペースから予約済みスペースに移動し、予約済みスペースの前の内容をパターンスペースに移動します。ただし、予約済みスペースの最初の内容は何もないため、コマンドは適用されませんs。後で(たとえば、7行目で)表示すると$$<(上記のように)、新しい行を含むテキストをパターンスペースにインポートし(上記のように)、すべての改行をタブに置き換えて結果を印刷します。

  • ${…}入力の終わりに達すると、中かっこで囲まれたコマンドが実行されることを示します。これは$$<、予約済みスペースで最後の行(つまり、最後の行)をクリアするためにを表示したときに実行したのと同じコマンドです。

警告:POSIXでの動作は保証されませんsed。私はそれをGNUでテストしましたsed

答え2

$ cat ip.txt 
$$<002L_tbfl
Putative transcription factor 001R;
GO:0006355
GO:0046782
GO:0006351
IPR007031
$$<002L_FRG3G
Uncharacterized protein 002L;
GO:0033644
GO:0016021
IPR004251

$ perl -ne 'chomp if !eof; if($. > 1){print /\$\$</ ? "\n" : "\t"} print' ip.txt 
$$<002L_tbfl    Putative transcription factor 001R; GO:0006355  GO:0046782  GO:0006351  IPR007031
$$<002L_FRG3G   Uncharacterized protein 002L;   GO:0033644  GO:0016021  IPR004251
  • chomp if !eofファイルの最後の行を除くすべての入力行から改行を削除します。
  • if($. > 1)1より大きい行番号を入力してください。
  • print /\$\$</ ? "\n" : "\t"行が一致する場合は改行を追加し$$<、そうでない場合はタップします。
  • print入力ライン印刷

答え3

おそらく32ビット制限があり、ストリーミングのみ可能です。次のようawkなものを使用できます

awk 'NR==1 {printf "%s",$0; next;} $1~/^\$\$</ {printf "\n%s",$0; next;} {printf "\t%s",$0;}' < file

$$<これにより、最初の行で始まる行(最初の行以降)を除いて、改行なしですべての入力行が連続して印刷されます。

たぶん、ENDセクションが必要な最後の改行文字が欲しいかもしれません。これらの変更を確認してくださいman awk

答え4

Ubuntu 12では、MawkとGawk 3.xで動作し、正規表現をサポートしていRSます。

$ awk 'BEGIN { RS="\\$\\$<"; FS="\n"; OFS="\t" } NF && $1="$$<"$1' data

出力:

$$<002L_tbfl    Putative transcription factor 001R; GO:0006355  GO:0046782  GO:0006351  IPR007031   
$$<002L_FRG3G   Uncharacterized protein 002L;   GO:0033644  GO:0016021  IPR004251

単に$$<改行文字をレコード区切り文字として使用し、改行文字をフィールド区切り文字として使用します。

これは次のことを意味します。

  • 入力はレコード区切り文字で始まるので、空のレコードを取得します。次の条件を使用してこの問題を解決しますNF。フィールド数はゼロでなければなりません。
  • $$<入力から削除されました。私たちはそれを入れました$1

中央にタブ付きのフィールドを印刷するには、タブを出力フィールド区切り記号(OFS)に設定します。 { print }モードのデフォルト動作なので無視します。

我々が修正したという事実は、すべてのフィールド結合を使用してレコード変数を更新する$1副作用もあります。この更新がない場合、元のレコードは改行などを含むそのまま印刷されます。$0OFS

関連情報