awk を使用して新しい行を空白に置き換えます。

awk を使用して新しい行を空白に置き換えます。

ディレクトリ内のすべてのファイルから生成されたテキストファイルがあります。このファイルを私が持っているスクリプトへの入力として使用したいが、正しく解析するには、特定の方法でフォーマットされたテキストファイルが必要です。

現在のテキストファイル(ファイル名リスト)の形式は次のとおりです。

A1_R1.fastq.gz
A1_R2.fastq.gz
A2_R1.fastq.gz
A2_R2.fastq.gz
A3_R1.fastq.gz
A3_R2.fastq.gz

RN各サンプルはタブで区切られ、同じ行になるようにペアになっている読み取り(同じ名前を持つが値が異なるファイル)が必要です。

A1_R1.fastq.gz A1_R2.fastq.gz
A2_R1.fastq.gz A2_R2.fastq.gz
A3_R1.fastq.gz A3_R2.fastq.gz

1000以上のアイテムがあるので、awkなどを使用してファイルを変更する方法が欲しいが、awkの経験はあまりありません。

答え1

質問に示すように行が並べ替えられていると仮定すると、このpasteコマンドは次のことができます。

$ paste - - < input_file
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz
A3_R1.fastq.gz  A3_R2.fastq.gz

-dデフォルトのTAB以外の項目で列を区切るには、このオプションを使用しますpaste。単純なスペースの場合:

$ paste -d ' ' - -  <input_file

答え2

すべてのラインペアが互いに隣接している表示入力の場合、awkに必要なものは次のとおりです。

$ awk '{ORS=(NR%2 ? "\t" : RS)} 1' file
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz
A3_R1.fastq.gz  A3_R2.fastq.gz

またはまだペアリングされていない場合:

$ shuf file > file1
$ cat file1
A3_R2.fastq.gz
A2_R2.fastq.gz
A1_R1.fastq.gz
A3_R1.fastq.gz
A1_R2.fastq.gz
A2_R1.fastq.gz

したがって、次の呼び出しを追加しても問題ない場合は、次のようにしますsort

$ awk '{ORS=(NR%2 ? "\t" : RS)} 1' <(sort file1)
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz
A3_R1.fastq.gz  A3_R2.fastq.gz

またはawkでペアリングします。

$ awk -F'_' -v OFS='\t' '$1 in a{print a[$1], $0; next} {a[$1]=$0}' file1
A3_R2.fastq.gz  A3_R1.fastq.gz
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R2.fastq.gz  A2_R1.fastq.gz

最後のスクリプトでは、場合によっては、R2フィールドがR1パートナーの前に出力されます。これが問題の場合は、印刷中に注文できます。

$ awk -F'_' -v OFS='\t' '
    $1 in a { print (a[$1] < $0 ? a[$1] OFS $0 : $0 OFS a[$1]); next }
    { a[$1] = $0 }
' file1
A3_R1.fastq.gz  A3_R2.fastq.gz
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz

入力ファイルに実際に数百万行がある場合は、以前に追加するとほとんどのdelete a[$1];場合next実行時間が速くなり、数千行にすぎない場合はそれほど価値がありません(delete a[$1]各ペアを呼び出すオーバーヘッドと大きなハッシュを持つオーバーヘッドを比較してみてください) )。表面a[])。

出力ラインをソートする必要がある場合は、GNU awkを使用する必要がありますPROCINFO["sorted_in"]

$ awk '{a[$0]} END{PROCINFO["sorted_in"]="@ind_str_asc"; for (i in a) printf "%s%s", i, (++n % 2 ? "\t" : RS) }' file1
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz
A3_R1.fastq.gz  A3_R2.fastq.gz

ただし、使用されている解決策と同様に、sort入力の数字が複数の数字になる可能性がある場合、予想される順序は生成されません。たとえば、A11以前はアルファベット順に並べられていたためですA2。各文字列を別々のアルファベットと数字の部分に分割する必要があります。各部分を別々に並べ替えるか、各位置に常に同じ数字のアルファベットと数字を含めるように正規化しますA1_R1000A0001_000R0001

答え3

使用幸せ(以前のPerl_6)


常にペアで読み、順序が正しい場合:

~$ raku -e '.put for lines.rotor(2);'  file 

常にペアで読み取ったが、ファイル名の順序が間違っている場合:

~$ raku -e '.put for lines.sort.rotor(2);'  file 

RakuはPerlファミリーのプログラミング言語です。 @EdMortonの優れた答えと同様に、awkファイル名を並べ替える必要がある場合、結果の順序はアルファベット順です。

https://docs.raku.org/routine/lines
https://docs.raku.org/routine/rotor
https://raku.org


ファイル名の順序に関係なく、ファイルが欠落している場合があります。

~$ raku -ne 'BEGIN my %hash;     \  
             %hash.append: .match(/^ (<-[_]>+) _ /).[0]  =>  $_;   \
             END for %hash.sort { .values.put };'   file

#OR

~$ raku -ne 'BEGIN my %hash;     \ 
             %hash.append: m/^ (<-[_]>+) _ /.[0]  =>  $_;    \
             END for %hash.sort { .values.put };'   file 

2番目の方法は、入力データがソースでない場合(ファイル名の欠落など)に適しています。 Perl自体と同様に、Rakuには("non-auto-print-line")フラグを介して呼び出されるawkコマンドラインに似たモードがあります。-ne上記では、BEGINaを宣言してこれを行います%hash。この「1行」本文では、各行は.matched onです(ここでは、行のテキストを保持するテーマ変数であるon関数を呼び出す略語が.matchあります)。$_.match$_

.match(または)ルーチンm/ … //オペレータは、^行の始まり、アンダースコア<-[_]>+以外の1つ以上の文字(カスタムの否定文字クラスなど)、アンダースコア自体を_検索します。_(参考用にのみカスタマイズしてください。ポジティブキャラクタークラスは次のとおりです<+[ … ]>。)。括弧は、下線が付いていない先行テキストを$0次のようにキャプチャします.[0]

.[0]したがって、各行はwith key$_フル行)として解釈されますvalue=> キーと値のペアを作成するために使用されます。ハッシュデータ構造は一意に保たれるため、同じ値が表示されるたびkeysに新しい値が得られます。読み取り行の最後にあるキーを押してから、各キーを取り出します。keyappendENDsortput.values

https://course.raku.org/essentials/associatives/hashes/
https://docs.raku.org/言語/hashmap
https://raku.org


入力例:

A1_R1.fastq.gz
A1_R2.fastq.gz
A2_R1.fastq.gz
A2_R2.fastq.gz
A3_R1.fastq.gz
A3_R2.fastq.gz

出力例(2つの方法のいずれか):

A1_R1.fastq.gz A1_R2.fastq.gz
A2_R1.fastq.gz A2_R2.fastq.gz
A3_R1.fastq.gz A3_R2.fastq.gz

答え4

私はそのファンですsed。隣接する電線対を簡単に接続できます。

sed 'N; s/\n/'$'\t''/' < input > output

真ん中にあるのは、$'\t'単一のタブ文字を渡すbash-ismですsed。実際にはリテラルタブを使用しますが、このメディアにはこれが明確に反映されません。sed 'N; s/\n/ /' < input > output

説明する:

  • sed最初の行から読んでください。
  • 次の入力行を読み、それを現在の入力行に追加し、改行文字Nで区切るように指示します。sed
  • このsコマンドは改行をタブに置き換えます。
  • これ以上コマンドがない場合は、前のステップの結果を書き、次の行を読み込み、sedループバックします。
  • sed入力がなくなると終了します。

関連情報