如何附加文件名中的字符串并将其插入到列中并进行修改?

如何附加文件名中的字符串并将其插入到列中并进行修改?

我使用以下命令创建 22 个文件:

user@host$ awk '{ print $1, $3, $4, $5 }' chr22.gen > snps22
user@host$ awk '{ print $1, $3, $4, $5 }' chr21.gen > snps21
...
user@host$ awk '{ print $1, $3, $4, $5 }' chr1.gen > snps1

输出文件如下所示:

user@host$ head snps21
rs885550 9887804 C T
rs169757 9928594 A C
rs210498 9928860 C T
rs210499 9929079 C A
rs303304 9941889 A G
...

我想做的是修改这些输出文件(snps22snps21snps20...),例如snps21如下所示:

user@host$ head snps21
rs885550 21:9887804:C:T
rs169757 21:9928594:A:C
rs210498 21:9928860:C:T
rs210499 21:9929079:C:A
rs303304 21:9941889:A:G
...

因此需要用chr21.gen冒号将输入文件名称中的数字(即 21)连接到输出文件的第二列,然后用冒号连接第二、第三和第四列。

答案1

假设您的文件完全按照您所显示的方式调用,即字符串snps后跟染色体名称,那么您可以使用

for name in snps*; do
    awk 'FNR == 1 { chr = substr(FILENAME, 5) }
         { printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) }' "$name" >"$name.new"
done

这将通过以下方式从文件名中提取染色体名称substr()(染色体名称是文件名中从第 5 个字符开始的所有字符)。仅当读取文件的第一行 ( FNR == 1) 时才会执行此操作。然后,代码以所需的格式输出当前行printf(),并包含染色体名称。

然后将数据写入带有.new文件名后缀的文件中。

awk可以通过选择在哪里写入输出来消除 shell 循环:

awk 'FNR == 1 { chr = substr(FILENAME, 5); name = FILENAME ".new" }
     { printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) >name }' snps* 

您想将所有输出收集在一个文件中吗?这样就足够了

awk 'FNR == 1 { chr = substr(FILENAME, 5) }
     { printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) }' snps* >all_snps

您还可以将修改后的变体应用于.gen您拥有的原始文件:

awk 'FNR == 1 { chr = substr(FILENAME, 4); sub("\.gen$", "", chr)
                name = "snps" chr }
     { printf("%s %s:%s:%s:%s\n", $1, chr, $3, $4, $5) >name }' chr*.gen

或者,对于单个输出文件,

awk 'FNR == 1 { chr = substr(FILENAME, 4); sub("\.gen$", "", chr) }
     { printf("%s %s:%s:%s:%s\n", $1, chr, $3, $4, $5) }' chr*.gen >all_snps

这只是从数据中选择稍微不同的列,并且必须提取文件名的另一部分来查找染色体的名称的问题。

答案2

使用 bash (以及 sed 和 tr)快速尝试:

for i in snps* 
do
  n=$(echo $i |tr -d 'a-zA-Z')
  sed -i -e "s/ / $n:/" -e 's/ \([A-Z]\)/:\1/g' $i
done

这只是循环遍历以 snps2 开头的文件集,对于每个文件,它从名称中删除所有字母字符以获得数字部分,然后使用 sed (a) 将第一个空格替换为空格,即文件的数字部分文件名和冒号,(b) 将大写字母后面的每个空格替换为冒号。我很确定使用 awk 也可以同样好地完成。

相关内容