![shell 命令中的单破折号和双破折号标志有什么区别?](https://linux22.com/image/583977/shell%20%E5%91%BD%E4%BB%A4%E4%B8%AD%E7%9A%84%E5%8D%95%E7%A0%B4%E6%8A%98%E5%8F%B7%E5%92%8C%E5%8F%8C%E7%A0%B4%E6%8A%98%E5%8F%B7%E6%A0%87%E5%BF%97%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%EF%BC%9F.png)
我是 shell 新手,这些命令的使用似乎很随意。一个标志有一个单破折号,而另一个标志可能有一个双破折号,这有什么原因吗?
答案1
单个连字符后可以跟多个单字符标志。双连字符可作为单个多字符选项的前缀。
考虑这个例子:
tar -czf
在此示例中,-czf
指定三个单字符标志:c
、z
和f
。
现在考虑另一个例子:
tar --exclude
在这种情况下,--exclude
指定一个名为 的多字符选项exclude
。双连字符消除了命令行参数的歧义,确保将tar
其解释为 ,而不是、、、、和的exclude
组合。e
x
c
l
u
d
e
答案2
这取决于程序。通常“-”用于“短”选项(一个字母,-h),“--”用于“长”(较长)选项(--help)。
短选项通常可以组合(因此“-h -a”与“-ha”相同)
在类 Unix 系统中,ASCII 连字符减号通常用于指定选项。该字符后面通常跟有一个或多个字母。如果参数本身只有一个连字符减号而没有任何字母,则通常指定程序应处理来自标准输入的数据或将数据发送到标准输出。某些程序使用两个连字符减号 (--) 来指定“长选项”,其中使用更具描述性的选项名称。这是 GNU 软件的常见功能。
答案3
这确实是一种惯例。但是,它可以帮助解析器更有效地了解传递给程序的选项。此外,还有一些简洁的实用程序可以帮助解析这些命令,例如getopt(3)
或非标准getopt_long(3)
帮助解析程序的参数。
这很好,因为我们可以组合多个简短的选项,就像其他答案所说的那样tar -xzf myfile.tar.gz
。
如果 有一个“lisa”参数ls
,那么输入 可能ls -lisa
与有不同的含义ls --lisa
。前者是l
、i
、s
和a
参数,而不是单词。
事实上,您可以写ls -l -i -s -a
,其含义与 完全相同ls -lisa
,但这取决于程序。
还有一些程序不遵守此惯例。最明显的是,对于我的视力来说,dd
和gcc
。
答案4
另一种情况是,当一个脚本调用另一个程序时,可能需要将第一个脚本的选项与传递给第二个程序的选项分开。例如,您可以编写一个 bash 函数来解析命令行,类似于下面的函数。然后使用类似于下面的命令行。在这种情况下,双破折号将每个程序的选项分开,并允许内置解析器的错误处理按预期工作。当然,可能存在需要处理的特殊情况。
firstscript --firstScriptOption -- --optForSecondProgram
# Parse the command line and set variables to control logic.
parseCommandLine() {
local additionalOpts exitCode optstring optstringLong
# Indicate specification for single character options:
# - 1 colon after an option indicates that an argument is required
# - 2 colons after an option indicates that an argument is optional, must use -o=argument syntax
optstring="h"
# Indicate specification for long options:
# - 1 colon after an option indicates that an argument is required
# - 2 colons after an option indicates that an argument is optional, must use --option=argument syntax
optstringLong="help"
# Parse the options using getopt command:
# - the -- is a separator between getopt options and parameters to be parsed
# - output is simple space-delimited command line
# - error message will be printed if unrecognized option or missing parameter but status will be 0
# - if an optional argument is not specified, output will include empty string ''
GETOPT_OUT=$(getopt --options ${optstring} --longoptions ${optstringLong} -- "$@")
exitCode=$?
if [ ${exitCode} -ne 0 ]; then
# Call a separate function to print usage.
printUsage
exit 1
fi
# The following constructs the command by concatenating arguments:
# - the $1, $2, etc. variables are set as if typed on the command line
# - special cases like --option=value and missing optional arguments are generically handled
# as separate parameters so shift can be done below
eval set -- "${GETOPT_OUT}"
# Loop over the options:
# - the error handling will catch cases were argument is missing
# - shift over the known number of options/arguments
while true; do
#echo "Command line option is ${opt}"
case "$1" in
-h|--help) # Print usage of this script
printUsage
shift
;;
--) # No more arguments - following arguments are passed to the second program.
shift
break
;;
*) # Unknown option - will never get here because getopt catches up front
# and remaining options are after --
echo "Invalid option $1." >&2
printUsage
exit 1
;;
esac
done
# Get a list of all command line options that do not correspond to dash options:
# - These are "non-option" arguments after --
# - For example, one or more file or folder names that need to be processed.
# - If multiple values, they will be delimited by spaces.
# - Command line * will result in expansion to matching files and folders.
shift $((OPTIND-1))
additionalOpts=$*
echo "Additional options: ${additionalOpts}"
# The additional options would be passed to the second program.
}