我有一个包含多个文件的文件夹。每个文件都有一个命名约定1000T.quant.sf、1000G.quant.sf、1001T.quant.sf、1001G.quant.sf等等。我写的脚本需要用头生成行进行修改。基本上,脚本拉第一列一次,并在所有文件中循环,为目录中的每个文件拉第5列,以生成包含这些列的整体矩阵。我遇到的问题是用正确的替换列标题。我想用每列*.quant.sf之前的字符串替换标题,但目前我有双标题。我该如何解决此问题?
代码段:
cut -f 1 `ls *quant.sf | head -1` > tmp
for x in *quant.sf; do
printf "t" >> tsamples
printf `echo $x | cut -d. -f 1` >> tsamples
cut -f 5 $x | paste tmp - > tmp2
mv tmp2 tmp
done
echo "" >> tsamples
cat tsamples tmp > transcipts.numreads
rm tsamples tmp
电流输出
1001G 1001T 1005G 1005T 1006G
Name NumReads NumReads NumReads NumReads NumReads
ENST00000456328.2 12.090 0.000 0.000 0.000 1.545
ENST00000450305.2 0.000 0.000 0.000 0.000 0.000
ENST00000488147.1 620.145 204.533 451.949 250.643 437.618
ENST00000619216.1 0.000 0.000 0.000 0.000 0.000
ENST00000473358.1 0.000 3.680 0.000 1.000 0.000
ENST00000469289.1 4.990 0.000 0.000 0.000 0.000
ENST00000607096.1 0.000 0.000 0.000 0.000 0.000
ENST00000417324.1 0.000 0.000 0.000 0.000 0.000
期望输出:
Name 1001G 1001T 1005G 1005T 1006G
ENST00000456328.2 12.090 0.000 0.000 0.000 1.545
ENST00000450305.2 0.000 0.000 0.000 0.000 0.000
ENST00000488147.1 620.145 204.533 451.949 250.643 437.618
ENST00000619216.1 0.000 0.000 0.000 0.000 0.000
ENST00000473358.1 0.000 3.680 0.000 1.000 0.000
ENST00000469289.1 4.990 0.000 0.000 0.000 0.000
ENST00000607096.1 0.000 0.000 0.000 0.000 0.000
ENST00000417324.1 0.000 0.000 0.000 0.000 0.000
一个输入文件内容:
$ head 1005T.salmon_quant.sf
Name Length EffectiveLength TPM NumReads
ENST00000456328.2 1657 1441.000 0.000000 0.000
ENST00000450305.2 632 417.000 0.000000 0.000
ENST00000488147.1 1351 1170.738 4.987413 250.643
ENST00000619216.1 68 69.000 0.000000 0.000
ENST00000473358.1 712 512.539 0.045452 1.000
ENST00000469289.1 535 323.000 0.000000 0.000
ENST00000607096.1 138 18.000 0.000000 0.000
ENST00000417324.1 1187 971.000 0.000000 0.000
ENST00000461467.1 590 376.000 0.000000 0.000
使用Name
标题初始化tsamples
。然后,在处理文件内容时,跳过第一行tail -n +2
。
printf "Name" >tsamples
tail -n +2 "$(ls *quant.sf | head -1)" | cut -f 1 > tmp
for file in *quant.sf; do
printf 't%s' "${file%%.*}" >> tsamples
tail -n +2 "$file" | cut -f 5 | paste tmp - > tmp2
mv tmp2 tmp
done
echo "" >> tsamples
cat tsamples tmp > transcipts.numreads
rm tsamples tmp
您还可以使用bash的%%
参数扩展运算符来删除.
中的所有内容,而不是管道到cut
。
另一个使用关联数组的wariant
#!/bin/bash
header='Namett' # initiate header
declare -A row # create associative array 'row' to store rows of data
for file in *.sf; {
header+="t${file%%.*}" # creating header by appending first part of filename
while read line; do # read file line by line
[[ $line =~ ame ]] && continue # skip header
raw=( $line ) # split line by converting to 'raw' array
name=${raw[0]} # get name
data=${raw[4]} # get data
row[$name]+="t$data" # append data to named row
done < $file
}; header+='n' # apend header with new line in the end
printf $header # print header
for key in "${!row[@]}"; { # print
printf "$key${row[$key]}n" # all
} # rows
测试:
$ ./ex
Name 1005G 1005T
ENST00000607096.1 0.000 4.000
ENST00000450305.2 0.000 3.000
ENST00000473358.1 1.000 1.000
ENST00000417324.1 0.000 0.000
ENST00000619216.1 0.000 3.000
ENST00000456328.2 0.000 1.000
ENST00000461467.1 0.000 0.000
ENST00000488147.1 250.643 230.43
ENST00000469289.1 0.000 0.000