【问题标题】:Convert rows based entry to column based in shell将基于行的条目转换为基于 shell 的列
【发布时间】:2012-03-08 11:31:32
【问题描述】:

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

文件示例(仅显示 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}'

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

【问题讨论】:

    标签: parsing shell data-conversion reformat


    【解决方案1】:

    这是使用 Perl 的一种方法:

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

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

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

    【讨论】:

    • 谢谢 ruakh。我刚刚用 Python 写了一个脚本,它的功能完全一样。
    【解决方案2】:

    你可以像这样使用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;等等。

    【讨论】:

      【解决方案3】:

      我认为您的原始awk 解决方案是正确的。尝试这个;我认为它是可读性和有效的很好的结合:

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

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

      【讨论】:

        猜你喜欢
        • 2017-10-06
        • 1970-01-01
        • 1970-01-01
        • 2020-04-17
        • 2012-01-02
        • 2021-08-27
        • 1970-01-01
        • 2018-05-25
        • 2020-08-18
        相关资源
        最近更新 更多