awk

awk

我有一个包含 1000 个文件的文件夹;前面的所有字符均mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp指个人 ID(例如 NA21117、NA21119、NA21126、..)

NA21117.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
NA21119.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
NA21126.mapped.ILLUMINA.bwa.GIH.low_coverage.20121211.bam_dp
NA21127.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
NA21137.mapped.ILLUMINA.bwa.GIH.low_coverage.20120522.bam_dp
NA21142.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
NA21143.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp

每个文件只有一行:

cat NA21143.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
1   115258827   10

对于每个文件,我想将单独的 ID 粘贴到文件的内容中并获得如下输出:

1   115258827   10 NA21143

有办法做吗?

答案1

普通的bash

for file in *.bam_dp; do 
    contents=$(< "$file")
    echo "$contents ${file%%.*}" > "$file"
done

对于多行文件,仍然可以使用普通的 bash 来完成

for file in *.bam_dp; do 
    mapfile -t contents < "$file"
    printf "%s\n" "${contents[@]/%/ ${file%%.*}}" > "$file"
done

笔记:

  • mapfile命令将文件读取到行数组中。
  • 参数${var/pattern/string}扩展对变量值进行搜索和替换。 (记录在案在手册中
    • 如果模式以模式开头,则%模式锚定在字符串的末尾。在这里,我匹配字符串末尾的空模式。
    • 该变量可以是数组扩展,在这种情况下,每个数组元素都会发生替换。

坦率地说,这种方法太聪明了,我会选择更明显的方法。

答案2

使用循环:

#!/bin/bash

shopt -s nullglob
for file in ???????.mapped.*bam_dp; do
  [[ -f "$file" ]] || continue
  id=${file%%.*}              # grab the ID from file name
  sed -i "s/$/ $id/" "$file"  # modify the file in-place
done

答案3

从 $ARGV 中删除 .* 然后将 \t $ARGV 附加到文件中:

perl -i -pe '$ARGV=~s/\..*//; s/$/\t$ARGV/;' NA*

格伦的解决方案很可能运行得更快:

perl -i -lpe '$_ .= " " . substr($ARGV,0,index($ARGV,"."))' NA*

但如果每个文件只有一行,则大多数时间将在驱动器上查找。

答案4

awk

此方法与 GNU (Linux) 和 BSD (Mac) 版本的awk.

awk '{ id=FILENAME ; sub(/\..*/,"",id) ; print $0 "\t" id }' *.bam_dp
  • id=FILENAME ; sub(/\..*/,"",id)
    将每个文件名的第一部分*.bam_dp(第一个之前的所有内容.)存储为id.
  • print $0 "\t" id
    打印每个文件的内容,然后打印制表符,然后打印记录的id.

这将打印一个包含行的列表,如您的示例所示:

1   115258827   10 NA21143

原始文件不会被修改。例如,您可以通过添加到> file.txt命令末尾来保存此输出。

相关内容