3

我创建了这个有一个参数(文件名)的小 Bash 脚本,该脚本应该根据文件的扩展名做出响应:

#!/bin/bash

fileFormat=${1}

if [[ ${fileFormat} =~ [Ff][Aa]?[Ss]?[Tt]?[Qq]\.?[[:alnum:]]+$ ]]; then
    echo "its a FASTQ file";
elif [[ ${fileFormat} =~ [Ss][Aa][Mm] ]]; then
    echo "its a SAM file";
else
    echo "its not fasta nor sam";
fi

它是这样运行的:

sh script.sh filename.sam

如果它是一个 fastq(或 FASTQ,或 fq,或 FQ,或 fastq.gz(压缩)),我希望脚本告诉我“这是一个 fastq”。如果是 sam,我想让它告诉我它是 sam,如果不是,我想告诉我它既不是 sam 也不是 fastq。

问题:当我没有考虑 .gz(压缩)场景时,脚本运行良好并给出了我预期的结果,但是当我尝试添加最后一部分以解决这种情况时发生了一些事情(见第三行,它说的部分 .?[[:alnum:]]+ )。这部分的意思是“在文件名中,在扩展名之后(在这种情况下为 fastq),后面可能有一个点加上一些单词”。

我的输入是这样的:

sh script.sh filename.fastq.gz

它有效。但是如果我输入: sh script.sh filename.fastq

它说它不是fastq。我想把最后一部分作为可选的,但如果我添加一个“?” 最后它不起作用。有什么想法吗?谢谢!我的问题是修复该部分以适用于这两种情况。

4

2 回答 2

4

你可以使用这个正则表达式:

fileFormat="$1"

if [[ $fileFormat =~ [Ff]([Aa][Ss][Tt])?[Qq](\.[[:alnum:]]+)?$ ]]; then
    echo "its a FASTQ file"
elif [[ $fileFormat =~ [Ss][Aa][Mm]$ ]]; then
    echo "its a SAM file"
else
    echo "its not fasta nor sam"
fi

这里(\.[[:alnum:]]+)?使最后一组可选,即点后跟 1+ 个字母数字字符。

当你运行它时:

./script.sh filename.fastq
its a FASTQ file

./script.sh fq
its a FASTQ file

./script.sh filename.fastq.gz
its a FASTQ file

./script.sh filename.sam
its a SAM file

./script.sh filename.txt
its not fasta nor sam
于 2019-01-08T15:17:51.057 回答
1

直接的问题是您需要在.[[:alnum:]]之后至少有一个字符.fastq。这本身很容易解决,*而不是+.

不过,正则表达式并不是解决这个问题的一个特别好的解决方案。

case $fileFormat in
    *.[Ff][Aa][Ss][Tt][Qq] | *.[Ff][Aa][Ss][Tt][Qq].*)
        echo "$0: $fileFormat is a FASTQ file" >&2 ;;
    *.[Ss][Aa][Mm] )
        echo "$0: $fileFormat is a SAM file" >%2 ;;
esac

一直便携回到原来的伯恩sh。在 Bash 4.x 中,您可以在比较之前将文件名小写,以简化 glob 模式。

还要注意诊断如何包含脚本名称并打印到标准错误而不是标准输出。

于 2019-01-08T15:13:50.917 回答