今天在看到自己以前写的脚本,实在看不过去了,就花了点时间调整了一下。
以前的脚本。
一开始的脚本是这样的。又臭又长(别不信,看下面)。真的是复制粘贴修改→又复制粘贴修改 → 又又复制粘贴修改(这句话就是刚刚 copy 的)
#meth_heatmap.pl
#########################################
# CG_cov_0_sorted.tsv
# Chr1 1128 1128 + 1 0 CG CGA 1.00 1
# Chr1 1129 1129 - 8 2 CG CGT 0.80 10
# Chr1 1140 1140 - 8 1 CG CGT 0.89 9
# Chr1 1142 1142 - 6 1 CG CGC 0.86 7
#########################################
# CG_Bismark.tab
# Chr1 1128 + 1 0 CG CGA
# Chr1 1129 - 8 2 CG CGT
# Chr1 1140 - 8 1 CG CGT
#########################################
# NIP_repeat_meth.bed
# Chr1 1001 1052 1_Telomere +
#########################################
mkdir meth_heatmap
awk '$7~/CG/{print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' cov0_sorted.tsv > meth_heatmap/CG_Bismark.tab
awk '$7~/CHG/{print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' cov0_sorted.tsv > meth_heatmap/CHG_Bismark.tab
awk '$7~/CHH/{print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' cov0_sorted.tsv > meth_heatmap/CHH_Bismark.tab
cd meth_heatmap
bgzip CG_Bismark.tab
bgzip CHG_Bismark.tab
bgzip CHH_Bismark.tab
tabix -C -p vcf CG_Bismark.tab.gz
tabix -C -p vcf CHG_Bismark.tab.gz
tabix -C -p vcf CHH_Bismark.tab.gz
# copy TE related data to here
cp ~/data//NIP_ViewBS_meth.bed ./
cp ~/data/NIP_repeat_up_2kb.bed ./
cp ~/data/NIP_repeat_down_2kb.bed ./
cp ~/biosoft/mysome_bin/BS_seq_script/meth_heatmap.pl ./
# CG
perl meth_heatmap.pl NIP_ViewBS_meth.bed CG_Bismark.tab.gz 20 > CG_bin_20.result
perl meth_heatmap.pl NIP_repeat_up_2kb.bed CG_Bismark.tab.gz 20 > CG_up_bin_20.result
perl meth_heatmap.pl NIP_repeat_down_2kb.bed CG_Bismark.tab.gz 20 > CG_down_bin_20.result
# CHG
perl meth_heatmap.pl NIP_ViewBS_meth.bed CHG_Bismark.tab.gz 20 > CHG_bin_20.result
perl meth_heatmap.pl NIP_repeat_up_2kb.bed CHG_Bismark.tab.gz 20 > CHG_up_bin_20.result
perl meth_heatmap.pl NIP_repeat_down_2kb.bed CHG_Bismark.tab.gz 20 > CHG_down_bin_20.result
# CHH
perl meth_heatmap.pl NIP_ViewBS_meth.bed CHH_Bismark.tab.gz 20 > CHH_bin_20.result
perl meth_heatmap.pl NIP_repeat_up_2kb.bed CHH_Bismark.tab.gz 20 > CHH_up_bin_20.result
perl meth_heatmap.pl NIP_repeat_down_2kb.bed CHH_Bismark.tab.gz 20 > CHH_down_bin_20.result
#########################################
# get averge meth per col
#########################################
##################
# CG
###################
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CG_bin_20.result > result_CG_bin_20_AVE.txt
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CG_up_bin_20.result > result_CG_up_bin_20_AVE.txt
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CG_down_bin_20.result > result_CG_down_bin_20_AVE.txt
# merge
cut -f 2-21 result_CG_up_bin_20_AVE.txt > temp1.txt
cut -f 2-21 result_CG_bin_20_AVE.txt > temp2.txt
cut -f 2-21 result_CG_down_bin_20_AVE.txt > temp3.txt
paste temp1.txt temp2.txt temp3.txt > temp.txt
awk '{print "CG""t"$0}' temp.txt > TE_CG_meth.txt
rm -rf temp*.txt
##################
# CHG
#################
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CHG_bin_20.result > result_CHG_bin_20_AVE.txt
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CHG_up_bin_20.result > result_CHG_up_bin_20_AVE.txt
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CHG_down_bin_20.result > result_CHG_down_bin_20_AVE.txt
# merge
cut -f 2-21 result_CHG_up_bin_20_AVE.txt > temp1.txt
cut -f 2-21 result_CHG_bin_20_AVE.txt > temp2.txt
cut -f 2-21 result_CHG_down_bin_20_AVE.txt > temp3.txt
paste temp1.txt temp2.txt temp3.txt > temp.txt
awk '{print "CHG""t"$0}' temp.txt > TE_CHG_meth.txt
rm -rf temp*.txt
###################
# CHH
###################
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CHH_bin_20.result > result_CHH_bin_20_AVE.txt
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CHH_up_bin_20.result > result_CHH_up_bin_20_AVE.txt
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CHH_down_bin_20.result > result_CHH_down_bin_20_AVE.txt
# MERGE
cut -f 2-21 result_CHH_up_bin_20_AVE.txt > temp1.txt
cut -f 2-21 result_CHH_bin_20_AVE.txt > temp2.txt
cut -f 2-21 result_CHH_down_bin_20_AVE.txt > temp3.txt
paste temp1.txt temp2.txt temp3.txt > temp.txt
awk '{print "CHH""t"$0}' temp.txt > TE_CHH_meth.txt
rm -rf temp*.txt
# merge all data
cat TE_CG_meth.txt TE_CHG_meth.txt TE_CHH_meth.txt > TE_CG_CHG_CHH_meth.txt
可以看到大概有 141 行,充满了大量的冗余,也不知道当时是怎么想的,居然愿意一个个敲进去。但是今天下午我看着莫名其妙的就受不了了,然后我就开始了进行简化。
第一部分:文件格式注释,不变
首先第一步注释不变,相关输入文件格式
#########################################
#meth_heatmap.pl
#########################################
# CG_cov_0_sorted.tsv
# Chr1 1128 1128 + 1 0 CG CGA 1.00 1
# Chr1 1129 1129 - 8 2 CG CGT 0.80 10
# Chr1 1140 1140 - 8 1 CG CGT 0.89 9
# Chr1 1142 1142 - 6 1 CG CGC 0.86 7
#########################################
# CG_Bismark.tab
# Chr1 1128 + 1 0 CG CGA
# Chr1 1129 - 8 2 CG CGT
# Chr1 1140 - 8 1 CG CGT
#########################################
# NIP_repeat_meth.bed
# Chr1 1001 1052 1_Telomere +
#########################################
第二部分:运行前一些文件的拷贝
文件复制过来不变,也可以通过变量指定
mkdir meth_heatmap
cd meth_heatmap
# copy TE related data to here
cp ~/data//NIP_ViewBS_meth.bed ./
cp ~/data/NIP_repeat_up_2kb.bed ./
cp ~/data/NIP_repeat_down_2kb.bed ./
第三部分:要改的大头
我从最后的
CGCHGCHH
结合输入文件格式进行入手(反正我就从尾至前入手的,思维诡异)
#########################################
# get averge meth per col
#########################################
##################
# CG
###################
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CG_bin_20.result > result_CG_bin_20_AVE.txt
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CG_up_bin_20.result > result_CG_up_bin_20_AVE.txt
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' CG_down_bin_20.result > result_CG_down_bin_20_AVE.txt
# merge
cut -f 2-21 result_CG_up_bin_20_AVE.txt > temp1.txt
cut -f 2-21 result_CG_bin_20_AVE.txt > temp2.txt
cut -f 2-21 result_CG_down_bin_20_AVE.txt > temp3.txt
paste temp1.txt temp2.txt temp3.txt > temp.txt
awk '{print "CG""t"$0}' temp.txt > TE_CG_meth.txt
rm -rf temp*.txt
可以看到这上面一部分,有很多重复的字眼。
下面我们来进行拆分
3.1
CG_bin_20.result > result_CG_bin_20_AVE.txt
CG_up_bin_20.result > result_CG_up_bin_20_AVE.txt
CG_down_bin_20.result > result_CG_down_bin_20_AVE.txt
这一部分明显看到了只有 bin_20、up_bin_20、down_bin_20
的差别,我们完全可以用循环来替代
for sample in bin_20 up_bin_20 down_bin_20
do
CG_${sample}.result > result_CG_${sample}_AVE.txt
result_CG_up_bin_20_AVE.txt > temp1.txt
result_CG_bin_20_AVE.txt > temp2.txt
result_CG_down_bin_20_AVE.txt > temp3.txt
paste temp1.txt temp2.txt temp3.txt > temp.txt
done
3.2
result_CG_up_bin_20_AVE.txt > temp1.txt
result_CG_bin_20_AVE.txt > temp2.txt
result_CG_down_bin_20_AVE.txt > temp3.txt
paste temp1.txt temp2.txt temp3.txt > temp.txt
我们可以看到当我们前面使用循环的时候,我们完全可以通过 linux
的 >>
追加命令将结果输入到同一个文件中,即:
for sample in up_bin_20 bin_20 down_bin_20
do
CG_${sample}.result > result_CG_${sample}_AVE.txt
result_${context}_${sample}_AVE.txt >> ${context}_temp.txt # 此文最后有三行信息,分别是 up_bin_20 bin_20 down_bin_20
done
3.3
那么我们自然发现了这个循环中,还有一个变量,那就是 CG
,那么我们将 CG
用变量来代替岂不是又可以不用重复复制(类似下面这样),就可以达到我们的效果了。
for sample in up_bin_20 bin_20 down_bin_20
do
CG_${sample}.result > result_CG_${sample}_AVE.txt
result_${context}_${sample}_AVE.txt >> ${context}_temp.txt # 此文最后有三行信息,分别是 up_bin_20 bin_20 down_bin_20
done
for sample in up_bin_20 bin_20 down_bin_20
do
CHG_${sample}.result > result_CG_${sample}_AVE.txt
result_${context}_${sample}_AVE.txt >> ${context}_temp.txt # 此文最后有三行信息,分别是 up_bin_20 bin_20 down_bin_20
done
for sample in up_bin_20 bin_20 down_bin_20
do
CHH_${sample}.result > result_CG_${sample}_AVE.txt
result_${context}_${sample}_AVE.txt >> ${context}_temp.txt # 此文最后有三行信息,分别是 up_bin_20 bin_20 down_bin_20
done
改起来:
for context in CG CHG CHH
do
for sample in up_bin_20 bin_20 down_bin_20;
do
perl meth_heatmap.pl NIP_ViewBS_${sample}.bed ${context}_Bismark.tab.gz 20 > ${context}_${sample}.result
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' ${context}_${sample}.result > result_${context}_${sample}_AVE.txt
cut -f 2-21 result_${context}_${sample}_AVE.txt >> ${context}_temp.txt
done
done
这样我们就避免了 3*3 = 9
次的复制粘贴。
3.4
然后我们想将 CGCHGCHH_temp.txt
每个文件中的信息,合并成一行,并且标名是哪一类信息。最后将三个文件中的信息合并为一个文件
paste - - -
: 表示每三行合并为一行,注意- -
之间有空格。
# merge CG CHG CHH to one file
# 本来这部分信息是可以加到循环中的,但是我不知道为什么我 shell 脚本中不生效,在 linux 直接运行是可以的。
# cat ${context}_temp.txt |paste - - - | awk -v context=${context} '{print context"t"$0}' > nonTE_gene_${context}_meth.txt
# 解决不了,没办法只能多写两行代码
cat CG_temp.txt |paste - - - | awk -v context=CG '{print context"t"$0}' > nonTE_gene_CG_meth.txt
cat CHG_temp.txt |paste - - - | awk -v context=CHG '{print context"t"$0}' > nonTE_gene_CHG_meth.txt
cat CHH_temp.txt |paste - - - | awk -v context=CHH '{print context"t"$0}' > nonTE_gene_CHH_meth.txt
cat nonTE_gene_CG_meth.txt nonTE_gene_CHG_meth.txt nonTE_gene_CHH_meth.txt > nonTE_gene_CG_CHG_CHH_meth.txt
好了,到目前位置我们的循环为下面这样
# get averge methylation values per bin
for context in CG CHG CHH
do
for sample in up_bin_20 bin_20 down_bin_20;
do
perl meth_heatmap.pl NIP_ViewBS_${sample}.bed ${context}_Bismark.tab.gz 20 > ${context}_${sample}.result
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' ${context}_${sample}.result > result_${context}_${sample}_AVE.txt
cut -f 2-21 result_${context}_${sample}_AVE.txt >> ${context}_temp.txt
done
done
# merge CG CHG CHH to one file
cat CG_temp.txt |paste - - - | awk -v context=CG '{print context"t"$0}' > nonTE_gene_CG_meth.txt
cat CHG_temp.txt |paste - - - | awk -v context=CHG '{print context"t"$0}' > nonTE_gene_CHG_meth.txt
cat CHH_temp.txt |paste - - - | awk -v context=CHH '{print context"t"$0}' > nonTE_gene_CHH_meth.txt
cat nonTE_gene_CG_meth.txt nonTE_gene_CHG_meth.txt nonTE_gene_CHH_meth.txt > nonTE_gene_CG_CHG_CHH_meth.txt
第四部分
我们回到前面这部分
awk '$7~/CG/{print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' cov0_sorted.tsv > meth_heatmap/CG_Bismark.tab
awk '$7~/CHG/{print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' cov0_sorted.tsv > meth_heatmap/CHG_Bismark.tab
awk '$7~/CHH/{print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' cov0_sorted.tsv > meth_heatmap/CHH_Bismark.tab
cd meth_heatmap
bgzip CG_Bismark.tab
bgzip CHG_Bismark.tab
bgzip CHH_Bismark.tab
tabix -C -p vcf CG_Bismark.tab.gz
tabix -C -p vcf CHG_Bismark.tab.gz
tabix -C -p vcf CHH_Bismark.tab.gz
# CG
perl meth_heatmap.pl NIP_ViewBS_meth.bed CG_Bismark.tab.gz 20 > CG_bin_20.result
perl meth_heatmap.pl NIP_repeat_up_2kb.bed CG_Bismark.tab.gz 20 > CG_up_bin_20.result
perl meth_heatmap.pl NIP_repeat_down_2kb.bed CG_Bismark.tab.gz 20 > CG_down_bin_20.result
# CHG
perl meth_heatmap.pl NIP_ViewBS_meth.bed CHG_Bismark.tab.gz 20 > CHG_bin_20.result
perl meth_heatmap.pl NIP_repeat_up_2kb.bed CHG_Bismark.tab.gz 20 > CHG_up_bin_20.result
perl meth_heatmap.pl NIP_repeat_down_2kb.bed CHG_Bismark.tab.gz 20 > CHG_down_bin_20.result
# CHH
perl meth_heatmap.pl NIP_ViewBS_meth.bed CHH_Bismark.tab.gz 20 > CHH_bin_20.result
perl meth_heatmap.pl NIP_repeat_up_2kb.bed CHH_Bismark.tab.gz 20 > CHH_up_bin_20.result
perl meth_heatmap.pl NIP_repeat_down_2kb.bed CHH_Bismark.tab.gz 20 > CHH_down_bin_20.result
这时候我们应该发现了,这还是一样的就和刚刚我们所改的变量一样,无非是 CGCHGCHH, bin_20、up_bin_20、down_bin_20
的差别,写成循环就是
for context in CG CHG CHH
do
# echo $context
awk -v context=${context} '$7~context {print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' ../cov0_sorted.tsv > ${context}_Bismark.tab
bgzip ${context}_Bismark.tab
tabix -C -p vcf ${context}_Bismark.tab.gz
# do get bed file per bin methylation
for sample in up_bin_20 bin_20 down_bin_20;
do
perl meth_heatmap.pl NIP_ViewBS_${sample}.bed ${context}_Bismark.tab.gz 20 > ${context}_${sample}.result
done
done
第五部分
这时候我们可以发现这个循环和我们最开始的那个循环完全可以套在一起,然后就得到了下面这个
# get averge methylation values per bin
cd meth_heatmap
for context in CG CHG CHH
do
# echo $context
awk -v context=${context} '$7~context {print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' ../cov0_sorted.tsv > ${context}_Bismark.tab
bgzip ${context}_Bismark.tab
tabix -C -p vcf ${context}_Bismark.tab.gz
# do get bed file per bin methylation
for sample in up_bin_20 bin_20 down_bin_20;
do
# echo $sample
perl meth_heatmap.pl NIP_ViewBS_${sample}.bed ${context}_Bismark.tab.gz 20 > ${context}_${sample}.result
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' ${context}_${sample}.result > result_${context}_${sample}_AVE.txt
cut -f 2-21 result_${context}_${sample}_AVE.txt >> ${context}_temp.txt
done
done
# merge CG CHG CHH to one file
cat CG_temp.txt |paste - - - | awk -v context=CG '{print context"t"$0}' > nonTE_gene_CG_meth.txt
cat CHG_temp.txt |paste - - - | awk -v context=CHG '{print context"t"$0}' > nonTE_gene_CHG_meth.txt
cat CHH_temp.txt |paste - - - | awk -v context=CHH '{print context"t"$0}' > nonTE_gene_CHH_meth.txt
cat nonTE_gene_CG_meth.txt nonTE_gene_CHG_meth.txt nonTE_gene_CHH_meth.txt > nonTE_gene_CG_CHG_CHH_meth.txt
最后
最后我们将前面不变的信息与后面的循环结合起来得到最终的命令:
#########################################
#meth_heatmap.pl
#########################################
# CG_cov_0_sorted.tsv
# Chr1 1128 1128 + 1 0 CG CGA 1.00 1
# Chr1 1129 1129 - 8 2 CG CGT 0.80 10
# Chr1 1140 1140 - 8 1 CG CGT 0.89 9
# Chr1 1142 1142 - 6 1 CG CGC 0.86 7
#########################################
# CG_Bismark.tab
# Chr1 1128 + 1 0 CG CGA
# Chr1 1129 - 8 2 CG CGT
# Chr1 1140 - 8 1 CG CGT
#########################################
# NIP_repeat_meth.bed
# Chr1 1001 1052 1_Telomere +
#########################################
mkdir meth_heatmap
cd meth_heatmap
# copy TE related data to here
cp ~/data//NIP_ViewBS_meth.bed ./
cp ~/data/NIP_repeat_up_2kb.bed ./
cp ~/data/NIP_repeat_down_2kb.bed ./
cp ~/biosoft/mysome_bin/BS_seq_script/meth_heatmap.pl ./
# get averge methylation values per bin
for context in CG CHG CHH
do
# echo $context
awk -v context=${context} '$7~context {print $1"t"$2"t"$4"t"$5"t"$6"t"$7"t"$8}' ../cov0_sorted.tsv > ${context}_Bismark.tab
bgzip ${context}_Bismark.tab
tabix -C -p vcf ${context}_Bismark.tab.gz
# do get bed file per bin methylation
for sample in up_bin_20 bin_20 down_bin_20;
do
# echo $sample
perl meth_heatmap.pl NIP_ViewBS_${sample}.bed ${context}_Bismark.tab.gz 20 > ${context}_${sample}.result
awk -F"t" '{for(i=2; i <= NF; i++)
{if($i == $i+0){sum[i]+=$i; denom[i] += 1;}}}
END{for(i=1; i<= NF; i++){line=line""sum[i]/(denom[i]?denom[i]:1)FS}
print line}' ${context}_${sample}.result > result_${context}_${sample}_AVE.txt
cut -f 2-21 result_${context}_${sample}_AVE.txt >> ${context}_temp.txt
done
done
# merge CG CHG CHH to one file
cat CG_temp.txt |paste - - - | awk -v context=CG '{print context"t"$0}' > nonTE_gene_CG_meth.txt
cat CHG_temp.txt |paste - - - | awk -v context=CHG '{print context"t"$0}' > nonTE_gene_CHG_meth.txt
cat CHH_temp.txt |paste - - - | awk -v context=CHH '{print context"t"$0}' > nonTE_gene_CHH_meth.txt
cat nonTE_gene_CG_meth.txt nonTE_gene_CHG_meth.txt nonTE_gene_CHH_meth.txt > nonTE_gene_CG_CHG_CHH_meth.txt
估摸算了一下最后除了必须的注释信息和文件拷贝,不到三十行。难怪我编程啥都没长进,都是平时懒得。一直这么懒,有提升才见鬼了。
个人水平有限,不喜勿喷,文中有哪些还可以优化的地方还恳请在评论区指点一下,谢谢。
我 shell 是真的很烂的。真的!