修复 phylip 生物信息学文件的标头以准确反映文件中更新的样本数量

修复 phylip 生物信息学文件的标头以准确反映文件中更新的样本数量

我正在使用一个数据集,由我一直在编辑的 phylip 文件组成。 Phylip 格式是一种生物信息学格式,其中包含样本数量和序列长度作为标题,后跟每个样本及其序列。例如:

5 10
sample_1 gaatatccga
sample_2 gaatatccga
sample_3 gaatatcgca
sample_4 caatatccga
sample_5 gaataagcga

我的问题是,在修剪这些数据集时,标头中的样本数量不再准确(例如,在上面的示例中可能会说五个,但我已经修剪为只有三个样本)。我需要做的是将样本计数替换为新的、准确的样本计数,但我不知道如何在不丢失序列长度数字(例如 10)的情况下做到这一点。

我有 550 个文件,因此不能简单地手动执行此操作。我可以对 wc 进行 for 循环,但我再次需要保留该序列长度信息,并以某种方式将其与新的、准确的 wc 结合起来。

答案1

如果我正确理解您的要求,您可以使用以下awk命令:

awk -v samples="$(($(grep -c . input)-1))" 'NR == 1 { $1=samples }1' input

samples将设置为文件中的行数input减一(因为您没有计算标题行)。

awk然后将第一行的第一列更改为新的样本编号并打印所有内容。


$ cat input
5 10
sample_1 gaatatccga
sample_2 gaatatccga
sample_3 gaatatccga
$ awk -v samples="$(($(grep -c . input)-1))" 'NR == 1 { $1=samples }1' input
3 10
sample_1 gaatatccga
sample_2 gaatatccga
sample_3 gaatatccga

使用 GNU awk,您可以使用该-i标志来修改适当的文件,但我更愿意制作第二组修改后的文件,以确保进行了正确的更改。

就像是:

for file in *.phy; do
    awk -v samples="$(($(grep -c . "$file")-1))" 'NR == 1 { $1=samples }1' "$file" > "${file}.new"
done

答案2

另一种选择是使用ed(当然!):

for f in input*
do 
  printf '1s/[[:digit:]][[:digit:]]*/%d\nw\nq' $(( $(wc -l < "$f") - 1 )) | ed -s "$f"
done

这会循环遍历文件(例如命名为input-something)并将一个简单的 ed 脚本发送到ed

  • 在线1,搜索并用s//另一个数字替换 () 行开头的一个或多个数字 - 该替换数字是计算输入的行长度减一的结果
  • 之后,w写出文件并
  • 然后q退出ed

答案3

在 Vim 中,运行:

:execute '1s/^[0-9]\+/' . (line('$')-1) . '/'

(也感谢这个答案为我指明了正确的方向。)

您还可以在循环中执行此操作,例如使用shell 循环:bufdo或仅使用 shellfor循环。

相关内容