解析可选和非可选参数
Parsing optional and not optional arguments
我是 bash 的新手,在阅读并尝试了很多关于如何解析参数的内容之后,我做不到我真正想做的事情,我想解析可选参数而不是可选参数。更具体地说,我想解析 3 个参数,第一个(一个 fastaq 文件)第二个(第二个可选的 fastaq 文件)第三个参数将是一个目录。
my_script.sh -f1 file1.fasta --f2 file2.fasta -d/home/folder1/folder2
或
my_script.sh -f1 file1.fasta -d /home/folder1/folder2
我尝试过很多方法,但我不知道如何让程序识别何时有两个fasta文件和一个目录,以及何时只有一个fasta文件和一个目录。
有了这个参数,我想把它们保存在变量中,因为它们稍后会被第三方使用。
我试过这个:
for i in "$@"; do
case $i in
-f1=|-fasta1=)
FASTA1="${i#=}"
shift # past argument=value
;;
-d) DIRECTORY=
shift 2
;;
-d=|-directory=) DIRECTORY="${i#=}"
shift # past argument=value
;;
--f2=|-fasta2=) FASTA2="${i#*=}"
shift # past argument=value
;;
*)
;;
esac
done
但我刚得到这个
scripts_my_first_NGS]$ ./run.sh -f1 fasta.fasta -d /home/folder1
FASTA1 =
DIRECTORY =
FASTA2 =
基本上,您需要为不与等号一起使用的选项版本添加单独的解析器。
您的 shift
命令也没有用,因为您正在处理 for
循环。所以将其转换为 while [[ $# -gt 0 ]]; do
循环。
我还添加了一些我建议添加的修改。
while [[ $# -gt 0 ]]; do
case in
-f1|-fasta1)
FASTA1=
shift
;;
-f1=*|-fasta1=*)
FASTA1=${1#*=}
;;
-d|-directory)
DIRECTORY=
shift
;;
-d=*|-directory=*)
DIRECTORY=${1#*=}
;;
-f2|fasta2)
FASTA2=
shift
;;
-f2=*|-fasta2=*)
FASTA2=${1#*=}
;;
-*)
echo "Invalid option: " >&2
exit 1
;;
--)
# Do FILES+=("${@:2}") maybe
break
;;
*)
# TODO
# Do FILES+=("") maybe
;;
esac
shift
done
with-equal 和 non-with-equal 选项的“解析器”也可以统一为
使用辅助函数:
function get_opt_arg {
if [[ == *=* ]]; then
__=${1#*=}
return 1
elif [[ ${2+.} ]]; then
__=
return 0 # Tells that shift is needed
else
echo "No argument provided to option ''." >&2
exit 1
fi
}
while [[ $# -gt 0 ]]; do
case in
-d|-directory|-d=*|-directory=*)
get_opt_arg "$@" && shift
DIRECTORY=$__
;;
-f1|-fasta1|-f1=*|-fasta1=*)
get_opt_arg "$@" && shift
FASTA1=$__
;;
-f2|fasta2|-f2=*|-fasta2=*)
get_opt_arg "$@" && shift
FASTA2=$__
;;
-*)
echo "Invalid option: " >&2
exit 1
;;
--)
# Do FILES+=("${@:2}") maybe
break
;;
*)
# TODO
# Do FILES+=("") maybe
;;
esac
shift
done
切勿自行解析命令行选项!
否则请使用 Bash 函数 getopts
, if you do not need GNU style long options or use use the GNU program getopt
。
以下示例使用数组 FASTA
。 FASTA1
是 ${FASTA[0]}
,FASTA2
是 ${FASTA[1]}
。在 getopts
的情况下,这使得可以多次使用一个选项字符 (-f
)。
使用 getopts
只有一个字符的选项:
#! /bin/bash
FASTA=()
DIRECTORY=
while getopts 'f:d:' option; do
case "$option" in
f)
FASTA+=("$OPTARG")
;;
d)
DIRECTORY="$OPTARG"
;;
*)
printf 'ERROR: Invalid argument\n' >&2
exit 1
;;
esac
done
shift $((OPTIND-1))
if [[ -z ${FASTA[0]} ]]; then
printf 'ERROR: FASTA1 missing\n' >&2
exit 1
fi
if [[ -z $DIRECTORY ]]; then
printf 'ERROR: DIRECTORY missing\n' >&2
exit 1
fi
printf 'FASTA1 = %s\n' "${FASTA[0]}"
printf 'FASTA2 = %s\n' "${FASTA[1]}"
printf 'DIRECTORY = %s\n' "$DIRECTORY"
用法:
run -f file1.fasta -f file2.fasta -d /home/folder1/folder2
将 getopt
与单字符和 GNU 风格的长选项混合使用:
#! /bin/bash
FASTA=()
DIRECTORY=
options=$(getopt -o d: -l f1: -l f2: -- "$@") || {
printf 'ERROR: Invalid argument\n' >&2
exit 1
}
eval set -- "$options"
while true; do
case "" in
--f1)
FASTA[0]=""
shift 2;;
--f2)
FASTA[1]=""
shift 2;;
-d)
DIRECTORY=""
shift 2;;
--)
shift
break;;
*)
break;;
esac
done
if [[ -z ${FASTA[0]} ]]; then
printf 'ERROR: FASTA1 missing\n' >&2
exit 1
fi
if [[ -z $DIRECTORY ]]; then
printf 'ERROR: DIRECTORY missing\n' >&2
exit 1
fi
printf 'FASTA1 = %s\n' "${FASTA[0]}"
printf 'FASTA2 = %s\n' "${FASTA[1]}"
printf 'DIRECTORY = %s\n' "$DIRECTORY"
用法:
run --f1 file1.fasta --f2 file2.fasta -d /home/folder1/folder2
我是 bash 的新手,在阅读并尝试了很多关于如何解析参数的内容之后,我做不到我真正想做的事情,我想解析可选参数而不是可选参数。更具体地说,我想解析 3 个参数,第一个(一个 fastaq 文件)第二个(第二个可选的 fastaq 文件)第三个参数将是一个目录。
my_script.sh -f1 file1.fasta --f2 file2.fasta -d/home/folder1/folder2
或
my_script.sh -f1 file1.fasta -d /home/folder1/folder2
我尝试过很多方法,但我不知道如何让程序识别何时有两个fasta文件和一个目录,以及何时只有一个fasta文件和一个目录。
有了这个参数,我想把它们保存在变量中,因为它们稍后会被第三方使用。
我试过这个:
for i in "$@"; do
case $i in
-f1=|-fasta1=)
FASTA1="${i#=}"
shift # past argument=value
;;
-d) DIRECTORY=
shift 2
;;
-d=|-directory=) DIRECTORY="${i#=}"
shift # past argument=value
;;
--f2=|-fasta2=) FASTA2="${i#*=}"
shift # past argument=value
;;
*)
;;
esac
done
但我刚得到这个
scripts_my_first_NGS]$ ./run.sh -f1 fasta.fasta -d /home/folder1
FASTA1 =
DIRECTORY =
FASTA2 =
基本上,您需要为不与等号一起使用的选项版本添加单独的解析器。
您的 shift
命令也没有用,因为您正在处理 for
循环。所以将其转换为 while [[ $# -gt 0 ]]; do
循环。
我还添加了一些我建议添加的修改。
while [[ $# -gt 0 ]]; do
case in
-f1|-fasta1)
FASTA1=
shift
;;
-f1=*|-fasta1=*)
FASTA1=${1#*=}
;;
-d|-directory)
DIRECTORY=
shift
;;
-d=*|-directory=*)
DIRECTORY=${1#*=}
;;
-f2|fasta2)
FASTA2=
shift
;;
-f2=*|-fasta2=*)
FASTA2=${1#*=}
;;
-*)
echo "Invalid option: " >&2
exit 1
;;
--)
# Do FILES+=("${@:2}") maybe
break
;;
*)
# TODO
# Do FILES+=("") maybe
;;
esac
shift
done
with-equal 和 non-with-equal 选项的“解析器”也可以统一为 使用辅助函数:
function get_opt_arg {
if [[ == *=* ]]; then
__=${1#*=}
return 1
elif [[ ${2+.} ]]; then
__=
return 0 # Tells that shift is needed
else
echo "No argument provided to option ''." >&2
exit 1
fi
}
while [[ $# -gt 0 ]]; do
case in
-d|-directory|-d=*|-directory=*)
get_opt_arg "$@" && shift
DIRECTORY=$__
;;
-f1|-fasta1|-f1=*|-fasta1=*)
get_opt_arg "$@" && shift
FASTA1=$__
;;
-f2|fasta2|-f2=*|-fasta2=*)
get_opt_arg "$@" && shift
FASTA2=$__
;;
-*)
echo "Invalid option: " >&2
exit 1
;;
--)
# Do FILES+=("${@:2}") maybe
break
;;
*)
# TODO
# Do FILES+=("") maybe
;;
esac
shift
done
切勿自行解析命令行选项!
否则请使用 Bash 函数 getopts
, if you do not need GNU style long options or use use the GNU program getopt
。
以下示例使用数组 FASTA
。 FASTA1
是 ${FASTA[0]}
,FASTA2
是 ${FASTA[1]}
。在 getopts
的情况下,这使得可以多次使用一个选项字符 (-f
)。
使用 getopts
只有一个字符的选项:
#! /bin/bash
FASTA=()
DIRECTORY=
while getopts 'f:d:' option; do
case "$option" in
f)
FASTA+=("$OPTARG")
;;
d)
DIRECTORY="$OPTARG"
;;
*)
printf 'ERROR: Invalid argument\n' >&2
exit 1
;;
esac
done
shift $((OPTIND-1))
if [[ -z ${FASTA[0]} ]]; then
printf 'ERROR: FASTA1 missing\n' >&2
exit 1
fi
if [[ -z $DIRECTORY ]]; then
printf 'ERROR: DIRECTORY missing\n' >&2
exit 1
fi
printf 'FASTA1 = %s\n' "${FASTA[0]}"
printf 'FASTA2 = %s\n' "${FASTA[1]}"
printf 'DIRECTORY = %s\n' "$DIRECTORY"
用法:
run -f file1.fasta -f file2.fasta -d /home/folder1/folder2
将 getopt
与单字符和 GNU 风格的长选项混合使用:
#! /bin/bash
FASTA=()
DIRECTORY=
options=$(getopt -o d: -l f1: -l f2: -- "$@") || {
printf 'ERROR: Invalid argument\n' >&2
exit 1
}
eval set -- "$options"
while true; do
case "" in
--f1)
FASTA[0]=""
shift 2;;
--f2)
FASTA[1]=""
shift 2;;
-d)
DIRECTORY=""
shift 2;;
--)
shift
break;;
*)
break;;
esac
done
if [[ -z ${FASTA[0]} ]]; then
printf 'ERROR: FASTA1 missing\n' >&2
exit 1
fi
if [[ -z $DIRECTORY ]]; then
printf 'ERROR: DIRECTORY missing\n' >&2
exit 1
fi
printf 'FASTA1 = %s\n' "${FASTA[0]}"
printf 'FASTA2 = %s\n' "${FASTA[1]}"
printf 'DIRECTORY = %s\n' "$DIRECTORY"
用法:
run --f1 file1.fasta --f2 file2.fasta -d /home/folder1/folder2