在shell中将基于行的条目转换为基于列的条目



我需要您的帮助,将多行条目放入不同的列中。并对文件中的所有条目执行相同操作。

文件示例(仅显示2个条目,有很多类似的条目):

>ABC
*
AGA-AUUCUC-CGGUUCAAUCU
|||
UCUAUAACCGCGCCGAGUUAGU
>ABC
*
AGAUAU-GCUGCAGGCUCAAUUG
||||||
UCUAUAACCGCG-CCGAGUUAGU

要求的文件格式:

>ABC AGA-AUUCUC-CGGUUCAAUCU UCUAUAACCGCGCCGAGUUAGU
>ABC AGAUAU-GCUGCAGGCUCAAUUG UCUAUAACCGCG-CCGAGUUAGU

我能够通过以下方式将单个条目转换为所需格式:

tr 'n' 't' <test3 | awk '{print $1,$3,$5}'

但如何通过读取整个文件来处理所有条目呢?

您可以这样使用awk

awk 'NR%2 { printf "%s%s", $0, (NR+1)%6 ? " " : "n" }' < test


解释:

关于awk,您需要了解以下两件事:

  • 语法为condition { commands },其中如果condition为真(非零)则执行commands

  • NR是当前记录的编号(即行号),从1开始。


这里,条件是NR%2,其对于奇数行是非零的。因此,该命令只对奇数行执行,而奇数行正是您要打印的行。偶数行被无声地丢弃。

printf将打印每一个奇数行,后跟一个空格或一个换行符。您的输入每6行重复一次,并且您希望在第5、11、17、行等行之后有一个换行符。你可以把这些数字加1,使其可以被6整除,所以公式(NR+1)%6对这些数字来说是0。

因此,(NR+1)%6 ? " " : "n"计算为第1行和第3行的一个空格,以及第5行的一条换行符。然后重复7、9和11;等等。

我认为您使用最初的awk解决方案是正确的。试试这个;我认为这是可读性和有效性的良好结合:

awk 'BEGIN { RS="nn" } ; { print $1, $3, $5 }' < myfile

这个想法是告诉awk将空行(2个连续的换行符)视为记录分隔符。然后,每个节都被视为一个单独的记录,空白(在本例中是单个换行符)将字段分隔开。这与您使用tr所做的非常相似,只是现在awk将一次运行整个文件处理一个节。

这里有一种使用Perl的方法:

perl -ne 'chomp; if($. % 2 == 1) { print $_, ($. % 6 == 5) ? "n" : "t" }'

这将打印文件的第1行、第3行、第5行、第7行等。在第5行、第11行、第17行等之后,它将打印一行换行符;在其他行之后,它将只打印一个选项卡。

(注意:这假设在连续的五行组之间只有一行空白。如果情况不是,请澄清。)

相关内容

  • 没有找到相关文章

最新更新