在OSX中使用awk拆分文本文件并在标头中添加行数

时间:2016-10-29 02:27:53

标签: macos awk

我想用包含数千行

的文本文件执行以下操作
  • 将文件拆分为以B开头的行(但不包括此行)。
  • 将每个拆分文件中的行数包括为标题+附加文本(即<number of lines> " 120"
  • 删除开始每一行的符号(即>

我尝试过以下代码,允许我拆分文件,但文件中存在的行数(如NR-1 " 120"中所示)是累积的,并且打印在拆分文件的最后而不是在开始。

awk '/^B/{n++; print NR-1 " 120" > filename;close(filename);next}{filename = "part" n ".txt"; print >filename}'

在我尝试将其打印为标题时,我使用了以下代码。但是假定的标题根本没有出现。 awk 'BEGIN{print NR-1 " 120" > filename}; /^B/{n++;close(filename);next};{filename = "part" n ".txt"; print >filename}' inputfile.txt

以上代码附带以下错误: awk: null file name in print or getline source line number 1

我的文本文件类似于:

>L1212 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L1222 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L1232 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
B       *        -                     |1|
>L4212 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4312 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4412 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4512 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
B       *        -                     |2|
>L4212 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4312 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4412 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4512 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4312 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4412 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
>L4512 ATCTATCTTCTATCTGTTAGCTAGCTAGCTA
B       *        -                     |3|

更新: 在不使用Mawk或GNU awk的情况下使用@ mklement0脚本的回旋处,我在textwrangler中使用grep将所有以B开头的行更改为单个字符~

1 个答案:

答案 0 :(得分:1)

使用GNU Awk或Mawk:

awk -v RS='\nB       \\*        -                     \\|[0-9]+\\|\n' 'NF {
  numLines = gsub("(^|\n)>", "\n") # replace line-initial ">" and count lines in block
  fname = "part" ++n               # determine next output filename
  printf "%s%s\n", numLines " 120", $0 > fname # output header + block
  close(fname)                               # close output file
}' file

注意:除非输入文件中的最后一行是分隔线,否则最后一个输出文件将有一个尾随空行(但是标题中的数据行计数是正确的) - OP有确认这不是问题。

  • 需要GNU Awk或Mawk,因为只有它们支持基于多字符的基于正则表达式的RS(输入记录分隔符)值 - 与macOS附带的BSD awk不同。 可能以不同的方式解决这个问题,但这会更麻烦。

    • GNU Awk和Mawk都可以通过包管理器Homebrew安装在macOS上;安装Homebrew后,只需运行brew install gawkbrew install mawk
  • 该方法通过B分隔符行将输入分解为行的。因此,每个这样的块必须作为一个整体适合存储器(可能是由于执行字符串替换而一次两个副本。

  • 写入输出文件之前将整个行存储在中,这样就可以预先计算行数并将该信息添加到标题

    • numLines = gsub("(^|\n)>", "\n")执行删除行初始>字符。并确定块中的行数,利用gsub()返回替换次数的事实。