![在 awk 中使用 bash 数组并引用变量:语法冲突问题](https://linux22.com/image/10946/%E5%9C%A8%20awk%20%E4%B8%AD%E4%BD%BF%E7%94%A8%20bash%20%E6%95%B0%E7%BB%84%E5%B9%B6%E5%BC%95%E7%94%A8%E5%8F%98%E9%87%8F%EF%BC%9A%E8%AF%AD%E6%B3%95%E5%86%B2%E7%AA%81%E9%97%AE%E9%A2%98.png)
我有一个脚本,其目的是:
- 对于文件列表,获取每个文件的具体编号(具体来说,这是测序数据)并将其存储到 array1 中
- 使用array1,找到最小的数字是array1
- 根据 array1 中最小的数字,将其全部除以 array1 中的所有数字,得到 array2。
我的脚本如下所示:
#!/usr/bin/bash
USAGE() { echo "Usage: bash $0 [-b <in-bam-files-dir>] [-o <out-dir>] [-c <chromlen>]" 1>&2; exit 1; }
if (($# == 0))
then
USAGE
fi
while getopts ":b:o:c:h" opt
do
case $opt in
b ) BAMFILES=$OPTARG
;;
o ) OUTDIR=$OPTARG
;;
c ) CHROMLEN=$OPTARG
;;
h ) USAGE
;;
\? ) echo "Invalid option: -$OPTARG exiting" >&2
exit
;;
: ) echo "Option -$OPTARG requires an argument" >&2
exit
;;
esac
done
if [ ! -d ${OUTDIR} ]
then
mkdir ${OUTDIR}
fi
if [ ! -d ${OUTDIR}/temp ]
then
mkdir ${OUTDIR}/temp
fi
if [ -d ${BAMFILES} ]
then
echo -e "\nProcessing BAM files from following directory: ${BAMFILES} \n "
fi
module purge
module load samtools
module load bedtools
module load ucsctools
echo -e "Modules are loaded\n"
FIRSTBAM=$(ls $BAMFILES/*bam | head -1)
MIN=$(samtools view -c -F 260 ${FIRSTBAM} )
echo -e "Minimum number of reads is currently set to $MIN from $FIRSTBAM (first bam in directory)\n"
declare -A BAMREADS
echo "BAMREADS array is initialized"
for i in $(ls $BAMFILES/*bam)
do
echo "Counting reads in $i "
BAMREADS[$i]=$(samtools view -c -F 260 $i)
done
for i in ${BAMREADS[@]}
do
if [[ $i -lt $MIN ]]
then
MIN=$i
fi
done
echo -e "Minimum number of reads that will be used for scaling is $MIN \n"
declare -A BAMFRACS
echo -e "BAMFRACS array is initialized"
for i in ${!BAMREADS[@]}
do
BAMFRACS[$i]=$(awk -v var1=${MIN} -v var2=${BAMREADS[$i]} 'BEGIN { x= var1 / var2; printf "%.8f", x }')
done
for i in $(ls $BAMFILES/*bam)
do
SAMPLE=`basename $i`
SAMPLE=${SAMPLE%.bam}
echo $SAMPLE
if [[ ${BAMREADS[$i]} -eq $MIN ]]
then
echo "Sample $i does not need scaling"
command="cp $i ${OUTDIR}/temp/${SAMPLE}.scaled.bam;
genomeCoverageBed -bg -split -ibam ${OUTDIR}/temp/${SAMPLE}.scaled.bam > ${OUTDIR}/temp/${SAMPLE}.bedgraph;
sed -e 's/^/chr/g;s/MT/M/g' ${OUTDIR}/temp/${SAMPLE}.bedgraph > ${OUTDIR}/temp/${SAMPLE}.modified.bedgraph;
sort -k1,1 -k2,2n ${OUTDIR}/temp/${SAMPLE}.modified.bedgraph > ${OUTDIR}/temp/${SAMPLE}.sorted.bedgraph;
bedGraphToBigWig ${OUTDIR}/temp/${SAMPLE}.sorted.bedgraph $CHROMLEN ${OUTDIR}/${SAMPLE}.bw"
#rm ${OUTDIR}/temp/${SAMPLE}.*
else
command="samtools view -s ${BAMFRACS[$i]} -b $i > ${OUTDIR}/temp/${SAMPLE}.scaled.bam;
genomeCoverageBed -bg -split -ibam ${OUTDIR}/temp/${SAMPLE}.scaled.bam > ${OUTDIR}/temp/${SAMPLE}.bedgraph;
sed -e 's/^/chr/g;s/MT/M/g' ${OUTDIR}/temp/${SAMPLE}.bedgraph > ${OUTDIR}/temp/${SAMPLE}.modified.bedgraph;
sort -k1,1 -k2,2n ${OUTDIR}/temp/${SAMPLE}.modified.bedgraph > ${OUTDIR}/temp/${SAMPLE}.sorted.bedgraph;
bedGraphToBigWig ${OUTDIR}/temp/${SAMPLE}.sorted.bedgraph $CHROMLEN ${OUTDIR}/${SAMPLE}.bw"
#rm ${OUTDIR}/temp/${SAMPLE}.*
fi
echo $command | qsub -V -cwd -o $OUTDIR -e $OUTDIR -l tmem=10G -l h_vmem=10G -l h_rt=3600 -N bigwig_${SAMPLE}
done
echo "Task completed: conversion jobs submitted to cluster"
我有两个问题:
据我了解,bash 不太擅长算术数学:即进行任何涉及浮点数的运算(加法、除法等)。但是,鉴于 var1 和 var2 在我的脚本中始终是整数(请参阅 $MIN 和所有 array1 值),我们是否同意这不是问题?即我的运算结果是浮点数,但它使用整数,所以这不是问题,对吗?
在 StackExchange 中不是很清楚,因为这里没有语法突出显示,但我注意到我的脚本的 var2=${BAMREADS[$i]} 部分不太正确。我使用 nano,在我的终端中,不像其他变量(如 ${MIN})那样将所有 ${BAMREADS[$i]} 都显示为红色,只有脚本的 ${BAMREADS[$i] 部分是显示为红色,即结尾]}不是红色。该脚本似乎按照我的预期运行,一切似乎都正常工作。所以我不太明白为什么它不全部是红色的。
这就是我的脚本在 nano 中的样子(请注意 awk 命令中 ${BAMREADS[$i]} 中的 ]} 以及稍后第二个 $command 中的 ]} 不是应有的红色):
但是,如果您将此代码粘贴到https://www.shellcheck.net/,在脚本的这一部分中突出显示不会遇到任何问题。那么为什么 nano 和 shellcheck 没有告诉我同样的事情呢?我已经使用了这个脚本,它似乎对我有用,但我担心这个突出显示的问题。
谢谢
答案1
语法高亮是一个问题
每个编辑器在这种方式上都有自己的缺点/优点。
请参阅我的问题软件推荐及其各自的答案,最重要的是这适用于 CLI 和 GUI和这对于图形用户界面。
尤其,视觉工作室代码, 有恕我直言GUI 编辑器中最好的语法突出显示。
从 CLI 编辑器中,请参阅 的答案gVim
,它为 CLI 执行相同的语法突出显示工作。
请注意,由于我是一个重度nano
用户,我可以告诉你nano
无法区分引号内的变量。
缺少双引号是一个更大的问题
最让你烦恼的是你没有使用 - 我想你不习惯 - 坏习惯 - 双引号。请参阅 StackOverflow 了解更多信息或直接使用 Google。或者参见下文。
双引号可防止通配符和分词
对于 shell 脚本编写者来说,nano
编辑器几乎不可用,因为它无法识别字符串(引号)内的变量,这对每个 shell 脚本编写者来说都是非常糟糕的。双引号在 shell 脚本中是完全必要的。他们防止所谓的通配符和分词,阅读ShellCheck 维基文章 SC2086有关此主题的更多信息。