使bash脚本漂亮而整洁

时间:2017-07-13 10:46:07

标签: bash shell awk

我在bash中做了一些事情,脚本占用了三个文件名并处理它们并将最终结果存储在第三个文件中。

脚本是:

#!/bin/bash

#clear

echo -n " Bam File "
read BamFile

echo -n " Region File "
read BedFile

echo -n " Output File "
read OutFile

awk '{print $1 "\t" $2 "\t" $3 "\t" $3-$2}' < $BedFile >Temp

coverageBed -abam $BamFile -b $BedFile -counts > bases

awk '{print $4 }' <bases >tempbases

paste -d "\t" Temp tempbases >TtTemp

samtools view -c -F 260 $BamFile > totalNumReads

cat totalNumReads | awk '{print $1}'>tags

tag=`cat tags`
echo " Number of tags present in file = $tag"

awk '{print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $5/($4/1000* "'$tag'"/1000000) } '<TtTemp > $OutFile

此脚本效果很好。

但是,我想对脚本进行以下调整。

我不想一个一个地询问文件名,而是想在开始时提供它们

类似的东西:

process.bash -bam BamFile.bam -region RegFile -Out OutFile

其中process.bash是我的脚本,并且在开始时提供了三个文件。

有人可以帮我这么做。

谢谢

2 个答案:

答案 0 :(得分:2)

您可以测试这样的参数:

#!/bin/bash

bam=null
reg=null
out=null

while [[ $# -gt 1 ]]; do
    arg="$1"
    case $arg in
        --bam)
            bam=$2
            shift
        ;;
        --reg)
            reg=$2
            shift
        ;;
        --out)
            out=$2
            shift
        ;;
        --help)
            helpmenu
        ;;
        *)
            shift
        ;;
    esac
    shift
done

function helpmenu() {
    echo -e "Your help text\n"
    exit 0
}

# Continue your script with the variables bam, reg and out
# ...

然后你可以像

一样使用你的脚本

$ process.bash --bam BamFile.bam --reg RegFile --out OutFile

那就是它。

您可以使用功能制作帮助菜单等内容。例如,我调用下面定义的函数helpmenu。然后它只是在回显后存在脚本。

编辑:

由于在这篇文章的评论中进行了长时间的讨论,让我说清楚一些事情:

在我看来,像我在帖子中那样处理每手的参数要强得多。原因是,它支持各种un * x系统(例如非POSIX系统)。

然后,因为声明只支持长命令:也支持短命令。我只是没有将它们添加到代码中,因为它没有被OP询问。例如,如果您希望能够传递-b file以及--bam file等文件,则只需相应地更改案例陈述:

-b|--bam)
    bam=$2
    shift
;;

我没有看到这个答案有什么问题,因为它提供了所要求的功能。我自己在所有脚本中使用这种方法,并且从未遇到过这样的问题。

答案 1 :(得分:2)

虽然循环遍历参数也是一个很好的解决方案,我想使用getopts命令提供解决方案。

我使用内部getopts,而不是扩展,它有几个限制(即你只能使用单个字符来引用参数)。

接下来,我提供了我发现的最类似的解决方案。

#!/bin/bash

  ##############################
  # HELPER METHODS
  ##############################

  # Parses the script arguments
  getArgs() {
    # Parse Options
    while getopts :hvb:r:o:-: flag; do
      # Treat the argument
      case "$flag" in
        h)
          # Display help
          usage
          ;;
        v)
          # Display version
          show_version
          ;;
        b)
          bamFile=${OPTARG}
          ;;
        r)
          regFile=${OPTARG}
          ;;
        o)
          outFile=${OPTARG}
          ;;
        -)
          # Check more complex arguments of the form --OPT, --OPT=VALUE
          case "$OPTARG" in
            help)
              # Display help
              usage
              ;;
            version)
              show_version
              ;;
            bam=*)
              # Get bam filename
              bamFile=$(echo $OPTARG | sed -e 's/bam=//g')
              ;;
            reg=*)
              # Get bam filename
              regFile=$(echo $OPTARG | sed -e 's/reg=//g')
              ;;
            out=*)
              # Get bam filename
              outFile=$(echo $OPTARG | sed -e 's/out=//g')
              ;;
            *)
              # Flag didn't match any patern. Raise exception
              display_error "${OPTARG}"
              ;;
          esac
          ;;
        *)
          # Flag didn't match any patern. Raise exception
          display_error "${OPTARG}"
          ;;
      esac
    done
  }

  usage() {
    echo "Usage: "
    exit 0
  }

  show_version() {
    echo "Version: "
    exit 0
  }

  display_error() {
    local argument=$1
    echo "[ERROR] Bad argument $argument"
    exit 1
  }

  ##############################
  # MAIN PROCESS
  ##############################
  getArgs "$@"

  echo "[DEBUG] BAM $bamFile"
  echo "[DEBUG] REG $regFile"
  echo "[DEBUG] OUT $outFile"

  awk '{ print $1 "\t" $2 "\t" $3 "\t" $3-$2 }' < $bedFile > Temp
  coverageBed -abam $bamFile -b $bedFile -counts > bases

  awk '{print $4 }' < bases > tempbases
  paste -d "\t" Temp tempbases > TtTemp
  samtools view -c -F 260 $bamFile > totalNumReads

  cat totalNumReads | awk '{ print $1 }' > tags
  tag=$(cat tags)
  echo " Number of tags present in file = $tag"
  awk '{ print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $5/($4/1000* "'$tag'"/1000000) }' < TtTemp > $outFile

一些示例输出:

$./process.sh -v
Version: 
$./process.sh --version
Version: 
$./process.sh -h
Usage: 
$./process.sh --help
Usage: 
$./process.sh -b bamfile -r regfile -o outfile
[DEBUG] BAM bamfile
[DEBUG] REG regfile
[DEBUG] OUT outfile
$./process.sh --bam=bamfile -rregfile --out=outfile
[DEBUG] BAM bamfile
[DEBUG] REG regfile
[DEBUG] OUT outfile

正如我所说,有一些限制。例如:

$./process.sh --bam=bamfile -rregfile -out=outfile
[DEBUG] BAM bamfile
[DEBUG] REG regfile
[DEBUG] OUT ut=outfile

虽然用户试图指定其他内容,但它是有效的条目。从我的角度来看,你应该在解析之后和开始这个过程之前检查bamFile,regFile,outFile值。