2020-07-03 常用有趣命令之?dāng)?shù)據(jù)處理

0.常見格式解壓縮

1. .tar.gz(或 .tgz) 文件
# 基本解壓(保留原壓縮文件)
tar -xzvf filename.tar.gz
# 解壓到指定目錄
tar -xzvf filename.tar.gz -C /path/to/target_dir
# 僅解壓特定文件(支持通配符)
tar -xzvf filename.tar.gz --wildcards "*.txt"
# 壓縮單個文件或目錄
tar -czvf output.tar.gz /path/to/source
# 壓縮多個文件或目錄
tar -czvf output.tar.gz file1.txt dir1/ file2.txt

2. .gz文件
# 解壓并刪除原 .gz 文件(默認(rèn)行為)
gzip -d filename.gz
# 或使用 gunzip(等效)
gunzip filename.gz
# 解壓并保留原 .gz 文件
gunzip -c filename.gz > output_file
# 或
gzip -dc filename.gz > output_file
# 壓縮文件(默認(rèn)刪除原文件,生成 .gz)
gzip filename
# 壓縮并保留原文件
gzip -c filename > filename.gz
# 指定壓縮級別(1-9,9為最高壓縮率,默認(rèn)6)
gzip -9 filename

3. .zip文件
# 基本解壓
unzip filename.zip
# 解壓到指定目錄
unzip filename.zip -d /path/to/target_dir
# 僅列出壓縮包內(nèi)容,不解壓
unzip -l filename.zip
# 解壓特定文件(支持通配符)
unzip filename.zip "*.txt"
# 壓縮單個文件或目錄(-r 遞歸目錄)
zip -r output.zip /path/to/source
# 壓縮多個文件或目錄
zip -r output.zip file1.txt dir1/ file2.txt
# 分卷壓縮(每個卷最大 100M)
zip -r -s 100m output.zip large_dir/
  1. 第一列相同時數(shù)據(jù)整理
input:
A  12 9
A  -0.3 2.3
B  1.0 -4
C  34 1000
C  -111 900
C  99 0.09

Output required:
A 12 9 -0.3 2.3
B 1.0 -4
C 34 1000 -111 900 99 0.09

Five codes:
sort inputfile | awk '{if(a!=$1) {a=$1; printf "\n%s%s",$0,FS} else {a=$1;$1="";printf $0 }} END {printf "\n" }' 
awk '{a[x++]=$0;b[xx++]=substr($0,1,1)}END{for(i=0;i<x;i++)if(b[i]==b[i+1]){f=f?f a[i+1]:f a[i]a[i+1]}else{if(f=="")f=a[i];gsub(b[i]" ","",f); print b[i] f;f=""}}' unsorted.inputfile
sort inputfile |awk '$1!=p{if(p)print s; p=$1; s=$0; next}{sub(p,x); s=s $0} END{print s}' 
awk '{k=$1=$1; sub(k,x); A[k]=A[k] $0} END{for(i in A)print i A[i]}' unsorted.inputfile
sort inputfile | awk  '{a[$1]=a[$1]?a[$1]" "$2:$2}END{for (i in a) print i,a[i]}'  #僅適合兩列的數(shù)據(jù)類型

2.某列相同時只保留某列最大的那一行

Output required:
#第一列相同時,保留第二列最大的一行
A  12 9
B  1.0 -4
C  99 0.09
sort -k1,1 -k2,2nr inputfile |awk '!a[$1]++{print}'

3.最強(qiáng)多行變一行

awk 'BEGIN{FS=RS;RS=KS}$1=$1'
awk '{ORS="\t";$1=$1; print $0}' 

4.求某列數(shù)據(jù)的標(biāo)準(zhǔn)差,方差,均值,樣本數(shù)(行數(shù))

echo "6,3
> 2,4,5
> 5,a,6
> 3,5,4
> 4,4,5">ppp
awk -F "," '{print $1}'  ppp|    awk   '{x[NR]=$0; s+=$0; n++} END{a=s/n; for (i in x){ss += (x[i]-a)^2} sd = sqrt(ss/n); print "SS""\t"sd,ss,a,n}' 
SS      1.41421 10 4 5
#多列同時求和,此例求一三列
awk '{FS = OFS = "," }{sum1 += $1; sum2 += $3}END { print sum1, sum2 }'   ppp

5.替換

sed -e 'y/ATCG/atcg/' seq.fna  #對應(yīng)替換之修改大小寫
sed -e '/>/!y/ATCG/atcg/' seq.fna  #對應(yīng)替換之DNA序列反向互補(bǔ)配對,并修改大小寫
sed  '100,2000s/GI/gi/g' seq.fa  #則只替換100行到2000行的內(nèi)容;
sed  '100,2000!s/GI/gi/g' seq.fa  #加感嘆號取反,在這個范圍之外的執(zhí)行操作;
sed 's/:.*//g' seq.fna   #刪除冒號之后的所有內(nèi)容;
sed 's/gi/GI/' seq.fna  #將文件中g(shù)i全部替換為大寫GI;
sed 's/\<gi\>/GI/' seq.fna  #精準(zhǔn)替換,不會把a(bǔ)giii替換為aGIii;
sed -i 's/gi/GI/g' seq.fna   #在原文件上進(jìn)行替換,并且進(jìn)行全部替換;
sed -i.bak 's#GI#gi#' seq.fna  #在原文件上進(jìn)行替換,并進(jìn)行備份;
sed -e 's/gi/GI/2;s/ref/REF/2' seq.fna   #只將第二次出現(xiàn)的gi和ref進(jìn)行替換;
sed -f sed.list cds.list    #根據(jù)文件中的模式進(jìn)行替換,可同時進(jìn)行多條件替換;
sed -n 's/gi/GI/p' seq.fna  #打印發(fā)生替換的行;
awk '{sub(/test/, "no", $0);print}' input.txt #進(jìn)行替換,類似sed的功能。

6.輸出行

sed -n '1307p'  seq.fna   #輸出文件第1307行;
sed -n '100,200' seq.fna  #輸出文件第100到200行;
sed -n '/ref/p' seq.fna   #輸出文件中包含ref關(guān)鍵字的行;
awk ’{if ($3>=80 && $4>=100) print $0}'  blast_m8.out  #過濾blast比對結(jié)果,將identity 大于80,并且比對長度大于100bp的結(jié)果輸出;
awk '$0~ /wang/{print $0}' passwd.list   #利用正則表達(dá)式,將秘密表中姓wang的賬戶都輸出出來;
awk 'NR>=20&&NR<=80' input.txt  #輸出第20到第80行內(nèi)容。

7.輸出列

awk -F ":" '{print $1,$NF}' passwd.list   #通過-F修改默認(rèn)分隔符為冒號,輸出第一行與最后一行;

8.去重

sort -u file;
sort file|uniq;
uniq -d file #僅顯示重復(fù)出現(xiàn)的行列,顯示一行。
uniq -D file #顯示所有重復(fù)出現(xiàn)的行列,有幾行顯示幾行。
uniq -u file #僅顯示出一次的行列
uniq -s N file #忽略比較前面的N個字符。
uniq -w N file #對每行第N個字符以后的內(nèi)容不作比較。
awk '!($0 in a) {a[$0];print}' input.txt  # 打印不重復(fù)的行,類似uniq的功能;
awk '!($2 in l){print;l[$2]=1}' input.txt #計算第二列內(nèi)容非冗余的次數(shù),類似于uniq的功能。
sort file|uniq -c |awk '{if($1==3) print $0}'  #提取重復(fù)三次的項

9.一行變多行

input:
A 12 9;-0.3 2.3
B 1.0 -4
C 34 1000;-111 900;99 0.09

Output required:
A  12 9
A  -0.3 2.3
B  1.0 -4
C  34 1000
C  -111 900
C  99 0.09

sed -r '/;/s/(\S+)\s+([^;]+);/\1 \2\n\1 /;P;D' input > Output

10.awk浮點(diǎn)數(shù)計算要雙精度校準(zhǔn)才能保證真正準(zhǔn)確,尤其是在小數(shù)點(diǎn)后9位以后。因?yàn)閍wk的默認(rèn)精度范圍是53bit,也就是雙精度的范圍內(nèi),因此在做高精度數(shù)值計算時,一定要注意浮點(diǎn)數(shù)的精度要求。

#不加雙精確
echo 57760731.179959 | awk  '{sum+=$1}END{printf("%.10f\n",sum)}'
57760731.1799589992
#加雙精度
echo 57760731.179959 | awk -M -v PREC=100 -v CONVFMT=%.30g '{sum+=$1}END{printf("%.10f\n",sum)}'
57760731.1799590000

11.保留兩位小數(shù)

#awk-僅一列數(shù)據(jù)
echo '4.667,9.888
3.442,3.44203
3.2214,4.302' > input
#awk-只第一列
awk '{printf "%.2f\n",$1}' input
#awk-兩列同時
awk '{num1=sprintf("%.2f",$1); num2=sprintf("%.2f",$2);print num1,num2}' input
#awk,常規(guī)print,很巧妙的利用int
awk '{print int($1*100)/100,$2}'
#bc
echo "scale=2;3/8" |bc #scale=2將小數(shù)位個數(shù)設(shè)置為2
0.37

12.兩文件取交集

gawk 'ARGIND==1{a[$1]=$1} ARGIND==2{if(a[$1]!="") print $0}' geneid.txt tpm.txt > gene.tpm.txt
awk 'NR==FNR{a[$1]=$0}NR>FNR{if($1 in a)print a[$1]"\t"$0}' A B > C
awk 'NR==FNR{a[$1]=$0;next}{if ($1 in a){print a[$1]"\t"1} else {print $0"\t"0}}' A B  > C
grep -w -A 1 -Ff genename gene.fasta --no-group-separator > genename.fasta

13.兩文件取差集、并集、交集

echo "a
b
c
d" > a

echo "b
c
d
e
f"> b

#交集
sort a b | uniq -d
b
c
d

#并集
sort a b| uniq 
a
b
c
d
e
f

#差集
#a特有
sort a b b | uniq -u
a

#b特有
sort b a a | uniq -u
e
f
  1. 輸出某字符串的前三個字符
echo 123456|awk '{print substr($1,1,3)}'

15.for循環(huán)嵌套時避免重復(fù)運(yùn)算,及自己比自己

for((i=1;i<=14;i++));  
do   
for((j=$i+1;j<=14;j++));  
do  
echo ${i}_vs_${j}
done
done

16.特殊情況下需要比較兩列去重

echo "1 2
2 1
1 1
2 4">input
cat input| awk '$1 != $2'
1 2
2 1
2 4
sort input| awk '!(SEEN[$1,$2]++) && !(($2,$1) in SEEN)' 
1 2
2 4

17.大神整理的單行命令集合
bioinformatics-one-liners
18.行列轉(zhuǎn)換

#輸出的分隔符有點(diǎn)亂
cat file.txt | awk 'BEGIN{c=0;} {for(i=1;i<=NF;i++) {num[c,i] = $i;} c++;} END{ for(i=1;i<=NF;i++){str=""; for(j=0;j<NR;j++){ if(j>0){str = str" "} str= str"\t"num[j,i]}printf("%s\n", str)} }' 

#推薦
cat file.txt | awk '{for(i=1;i<=NF;i=i+1){a[NR,i]=$i}}END{for(j=1;j<=NF;j++){str=a[1,j];for(i=2;i<=NR;i++){str=str "\t" a[i,j]}print str}}'

#最慢
cat file.txt | awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]"\t"$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' 

19.依據(jù)第一列做變量,相同時加和或者求均值

input:
A  12
A  3
B  1
C  34
C  11
C  99

求和

Output required:
A 15
B 1
C 144

awk '{s[$1] += $2}END{ for(i in s){  print i, s[i] } }'  input

求均值

Output required:
A 7.5
B 1
C 48

awk '{sum[$1]+=$2; count[$1]++} END {for (key in sum) {if (count[key]>1) {avg=sum[key]/count[key]; print key, avg} else {print key, sum[key]}}}' input.txt

20.awk求一列數(shù)的均值,最大值,最小值,中位數(shù)

input:
12
3
1
34
11
99

Output required:
mean:    26.6667
max:    99
min:    1
median:  12

 sort -n input | awk '{m[i++]=$1;if(min==""){min=max=$1}; if($1>max) {max=$1}; if($1<min) {min=$1}; total+=$1; count+=1} END {print "mean:\t" total/count,"\nmax:\t"max,"\nmin:\t"min,"\nmedian:\t "m[int(i/2)]}'

#表達(dá)矩陣,提取N個樣本均值大于0.5的基因
awk '{a=0;for(i=2;i<=NF;i++){if($i>0.5)a++};if(a>=2)print}' a.tsv

#計算變異系數(shù)
awk '{ sum += $1; sumsq += ($1)^2; n++ } END { mean = sum / n; sd = sqrt((sumsq - sum^2/n) / (n - 1)); cv = sd / mean * 100; print cv }' data.txt | bc

21.跳過前兩行,按照第一列數(shù)字,從大到小排序

echo "G C N
3 b D
1 2 9
5 2 3
2 3 4" > input
Output required:
G C N
3 b D
5 2 3
2 3 4
1 2 9
(awk 'NR<3' input && awk 'NR>2' input| sort -k1,1nr) > output

其實(shí)這個命題引出了shell里括號的用法,這里的小括號將命令做成了命令組,括號中的命令將會新開一個子shell順序執(zhí)行,所以括號中的變量不能夠被腳本余下的部分使用。 更多相關(guān)知識可見:shell中各種括號的作用

22.for循環(huán)1到10

for i in `echo 1 2 3 4 5 6 7 8 9 10`;do echo "${i}";done
for i in `seq 10`;do echo "${i}";done #10可為參數(shù)傳遞
for i in $(seq 1 1 10);do echo "${i}";done #10可為參數(shù)傳遞
for i in {1..10..1};do echo "${i}";done
for i in {1..10};do echo "${i}";done

23.幾種bed文件的sort策略

sortBed -i  input.bed
bedtools sort -i input.bed
sort -k 1,1 -k2,2n input.bed
sort -V -k 1,3 input.bed 
sort -V  -k 1,1 -k2,2n input.bed #通常這個最好用
-V參數(shù)重要, --version-sort          natural sort of (version) numbers within text

24.python模塊安裝

python2 -m pip install biopython --user
#  in a virtual environment or using Python 2
pip install biopython

#  for python 3 (could also be pip3.10 depending on your version)
pip3 install biopython

#  if you get permissions error
sudo pip3 install biopython
pip install biopython --user

#  if you don't have pip in your PATH environment variable
python -m pip install biopython  --user

#  for python 3 (could also be pip3.10 depending on your version)
python3 -m pip install biopython  --user

#  using py alias (Windows)
py -m pip install biopython

#  for Anaconda
conda install -c conda-forge biopython

#  for Jupyter Notebook
!pip install biopython

25.perl 模塊安裝

#非root用戶。推薦運(yùn)行下面的代碼獲取自己的私人cpan下載器。
wget -O- http://cpanmin.us | perl - -l ~/perl5 App::cpanminus local::lib
eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`
echo 'eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`' >> ~/.bashrc
echo 'export MANPATH=$HOME/perl5/man:$MANPATH' >> ~/.bashrc
#完成以上操作后以后只需要運(yùn)行以下命令即可
cpanm Convert::Color

# 不區(qū)分大小寫、加上了perl前綴、中間以短橫線連接
conda install -c bioconda perl-convert-color

26.輸出當(dāng)下系統(tǒng)時間

echo $(date +%Y-%m-%d" "%H:%M:%S)

27.整行均值過濾(跳過第一列)

cutvalue=`echo 1`
awk -vcut="${cutvalue}" '{a=0;for(i=2;i<=NF;i++){if($i>cut)a++};if(a>=2)print}' matrix.tsv

28.分組求均值
示例里是5個分組(sample)*5次重復(fù)的數(shù)據(jù)示例
修改的話,可按:6個時間點(diǎn),每個時間點(diǎn)3個重復(fù),改為-v sample=6 -v repeat=3即可。

awk -v sample=5 -v repeat=5 '{for(i=1;i<=sample;i++){I=(i-1)*repeat;sum=0;for(j=1;j<=repeat;j++){sum+=$(I+j+1)};if(allsum[$1]=="")allsum[$1]=$1"\t"sum/repeat; else allsum[$1]=allsum[$1]"\t"sum/repeat}}END{for(k in allsum)print allsum[k]}' a.tpm.tsv 
gene1  0         0.007919  0.0417744  436.062   833.515
gene2  83.9412   21.8847   45.4605    86.878    70.9082
gene3  11.1208   2.56975   7.76237    12.7182   11.5676

29.shell下按列名處理文件
使用bioawk軟件

$ cat b.txt
geneid  T1_1    T1_2    T1_3    T2_1    T2_2    T2_3
gene1   1       3       9       2       8       5
gene2   3       4       5       8       0       8
$ bioawk -t -c header '{print $geneid,$T1_1,$T2_1}' b.txt
geneid  T1_1    T2_1
gene1   1       2
gene2   3       8

使用awk,但是很繞

$ awk 'BEGIN{OFS="\t"}NR==1{for(i=1;i<=NF;i++){a[$i]=i}}NR>=1{print $a["geneid"],$a["T1_1"],$a["T2_1"]}' b.txt
geneid  T1_1    T2_1
gene1   1       2
gene2   3       8

30.awk來做長數(shù)據(jù)和寬數(shù)據(jù)之間的轉(zhuǎn)換

echo "a|A|10
a|B|0
b|C|10" |sed 's/|/\t/g' > test.long

cat test.long | awk -F'\t' '{data[$2][$1]=$3; samples[$1]} END {header="id"; for(sample in samples){header=header"\t"sample} print header; for(gene in data){output=gene; for(sample in samples){output=output"\t"(data[gene][sample]?data[gene][sample]:"0")} print output}}' > test.long2wide

cat test.long2wide | awk -F'\t' 'NR==1{for(i=1; i<=NF;i++){headers[i] = $i}}NR>1{for(i = 2; i <= NF; i++) {print $1 "\t" headers[i] "\t" $i}}'  > test.wide2long

reference:
https://www.unix.com/shell-programming-and-scripting/188147-how-merge-multiple-rows-into-single-row-if-first-column-matches.html
https://mp.weixin.qq.com/s/FTi2PwMlDdmWsn2Db71uSA
http://www.itdecent.cn/u/e86db5f5bbb8

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容