POSIX 和 GNU 有其选项的语法样式。对于我见过的所有命令,它们接受类似选项的输入作为命令行参数。
程序接受来自 stdin 的类似选项的输入(因此用于getopt
解析类似选项的 stdin 输入)是否不常见?就像是:
$ ls -l
-rw-rw-r-- 1 t t 31232 Jan 7 13:38 fetch.png
-rw-rw-r-- 1 t t 69401 Feb 6 14:35 proxy.png
$ myls
> -l
-rw-rw-r-- 1 t t 31232 Jan 7 13:38 fetch.png
-rw-rw-r-- 1 t t 69401 Feb 6 14:35 proxy.png
> -l fetch.png
-rw-rw-r-- 1 t t 31232 Jan 7 13:38 fetch.png
为什么 stdin 输入具有类似选项的输入并不常见,而命令行参数却很常见?
从表达能力的角度来看(类似于常规语言与上下文无关语言),像输入这样的非选项和像输入这样的选项是否等效?
我们不要强调 shell 扩展,因为我们从不期望(或需要)像 shell 扩展这样的事情发生在 stdin 输入上(类似非选项)。
谢谢。
对于非选项(如输入)的类似问题:https://stackoverflow.com/questions/54584124/how-to-parse-non-option-command-line-arguments-and-stdin-inputs(由于没有回复和否决,该帖子已被删除。但如果您有足够的声誉,仍然可以访问)
答案1
tl;dr 这与想要ls
在脚本中使用非常相似(1,2),仅在必要时引用,或者跨越流(这几乎就是字面意思,使用 stdin 来处理两个完全正交的东西)。这是个坏主意。
这种方法存在几个问题:
- 你的工具必须处理所有的扩展shell 已经为你处理了:
- 大括号扩展
- 波形符扩展
- 参数和变量扩展
- 命令替换
- 算术展开
- 分词
- 文件名扩展,包括通配符正如@StephenHarris指出的那样
- 如果您的工具无法处理任何扩展(正如你所建议的,与您给出的示例相反,该示例显然必须进行分词才能不将其视为
-l fetch.png
单个参数),您将必须向开发人员详细解释为什么没有-l "$path"
,-l ~/Downloads
并-l 'my files'
按照他们的期望进行操作。 - 当你的工具处理与 shell 不同的扩展(它会这样做,因为 shell 以不同的方式处理扩展,没有人能够检测到您正在运行的 shell 并永远支持所有这些),您刚刚添加了一个需要学习、记住和使用的新语法每个使用你的工具的人。
- 标准输入不再只是工具输入。基于Unix 哲学,它不能再与其他工具一起工作,因为其他工具必须执行特殊操作才能将输入传递给您的工具。
- 已经有一个约定每个主要工具。就以下方面而言,以如此根本的方式打破惯例将是一个非常糟糕的主意可用性。
- 混合选项和输入不能对于任意输入都可以安全地完成,除非您花费相当多的额外精力来编码或转义其中之一。
答案2
命令不会这样做,因为许多命令通常从标准输入获取数据。如果标准输入是选项和数据的混合,事情就会变得复杂(而且危险)。
答案3
这是非常Unix 程序在标准输入上接受命令行选项的情况并不常见。
它实际上会导致行为发生变化,因为在 Unix 世界中,文件名扩展(“globbing”)是由调用 shell 而不是应用程序执行的。
例如,如果你ls *.c
这样做,那么壳展开*.c
为file1.c
file2.c
,因此实际执行的是ls file1.c file2.c
。
如果您在标准输入上有值,那么程序将负责进行扩展。
所以...不仅不常见,而且在一般情况下这并不是一个好主意。
程序提示丢失数据的情况并不罕见
例如
#!/bin/bash
filename=$1
if [ -z "$filename" ]
then
read -p Filename: filename
fi
但这与在标准输入上获取命令行选项不同。