【问题标题】:Splitting text file and adding line count in header with awk in OSX在 OSX 中使用 awk 拆分文本文件并在标题中添加行数
【发布时间】:2017-03-11 23:01:45
【问题描述】:

我想对包含数千行的文本文件执行以下操作

  • 在以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 开头的行更改为单个字符 ~

【问题讨论】:

    标签: macos awk


    【解决方案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 分隔线将输入分成 行。因此,每个这样的块必须作为一个整体放入内存中(由于执行字符串替换,可能一次有两个副本。

    • 将整行代码块保存在内存中将它们写入输出文件是允许预先计算行数并将该信息添加到标题。 p>

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

    【讨论】:

    • 这行得通!虽然你能进一步解释一下每一行的代码吗?由于以 B 开头的行实际上在该行的其余部分包含一些填充文本,是否还有另一个输入可以删除该行的内容?例如。 B - - |1|,结束号码是按顺序排列的,所以这里的一揽子代码没有用处。
    • 只要它可以在 macOS 上设置,它就是一个选项。
    • 感谢脚本和提醒!这应该不是问题,因为软件会忽略空行。我暂时没有使用 GNU Awk 或 Mawk 在 TextWrangler 中使用 grep 解决了单字符问题。
    猜你喜欢
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多