lov*_*ish 2 awk text-processing bioinformatics
我有一个由目录中所有文件生成的文本文件。我想使用此文件作为我拥有的脚本的输入,但我需要以特定方式格式化文本文件才能正确解析。
目前,文本文件(文件名列表)的格式如下:
A1_R1.fastq.gz
A1_R2.fastq.gz
A2_R1.fastq.gz
A2_R2.fastq.gz
A3_R1.fastq.gz
A3_R2.fastq.gz
Run Code Online (Sandbox Code Playgroud)
我需要每个样本的配对读取(具有相同名称但不同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
Run Code Online (Sandbox Code Playgroud)
由于我有 >1000 个条目,我希望有一种使用 awk 或类似方法来修改文件的方法,但我对 awk 没有太多经验。
use*_*329 12
假设这些行按照您在问题中显示的方式排序,那么该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
Run Code Online (Sandbox Code Playgroud)
如果您希望用默认 TAB 以外的任何内容分隔列,请使用-d
选项paste
。对于一个简单的空间:
$ paste -d ' ' - - <input_file
Run Code Online (Sandbox Code Playgroud)
对于显示的输入,所有成对的行都彼此相邻,任何 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
Run Code Online (Sandbox Code Playgroud)
或者如果它们尚未配对:
$ 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
Run Code Online (Sandbox Code Playgroud)
因此,如果您不介意添加对以下内容的调用,则需要配对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
Run Code Online (Sandbox Code Playgroud)
或者在 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
Run Code Online (Sandbox Code Playgroud)
请注意,在最后一个脚本中,在某些情况下,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
Run Code Online (Sandbox Code Playgroud)
如果您的输入文件实际上有数百万行那么在大多数情况下添加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
Run Code Online (Sandbox Code Playgroud)
但是,就像使用 的解决方案一样sort
,当输入中的数字可以是多个数字时,它不会产生预期的顺序,因为例如,A11
之前会按字母顺序排序A2
- 您需要将每个字符串分成单独的字母顺序和数字部分,并分别对每个部分进行排序,或者将它们标准化为在每个位置中始终具有相同的数字字母和数字字符,例如在排序之前映射A1_R1
到000A0001_000R0001
或类似。