7 分钟阅读
https://linuxcommand.org/lc3_wss0120.php
When we last left our script, it looked something like this:
当我们上次离开我们的脚本时,它看起来像这样:
|
|
We have most things working, but there are several more features we can add:
我们已经完成了大部分工作,但还有几个功能可以添加:
We should be able to specify the name of the output file on the command line, as well as set a default output file name if no name is specified.
我们应该能够在命令行上指定输出文件的名称,如果没有指定名称,还应设置默认输出文件名。
Let’s offer an interactive mode that will prompt for a file name and warn the user if the file exists and prompt the user to overwrite it.
让我们提供一个交互模式,提示用户输入文件名,并在文件存在时警告用户并询问是否覆盖它。
Naturally, we want to have a help option that will display a usage message.
当然,我们希望有一个帮助选项,显示用法信息。
All of these features involve using command line options and arguments. To handle options on the command line, we use a facility in the shell called positional parameters. Positional parameters are a series of special variables ($0
through $9
) that contain the contents of the command line.
所有这些功能都涉及使用命令行选项和参数。为了处理命令行上的选项,我们使用Shell中的一个功能,称为位置参数。位置参数是一系列特殊变量($0
到$9
),它们包含命令行的内容。
Let’s imagine the following command line:
让我们想象以下命令行:
|
|
If some_program
were a bash shell script, we could read each item on the command line because the positional parameters contain the following:
如果some_program
是一个bash shell脚本,我们可以读取命令行上的每个项目,因为位置参数包含以下内容:
$0
将包含"some_program"$1
将包含"word1"$2
将包含"word2"$3
将包含"word3"Here is a script we can use to try this out:
以下是我们可以用来尝试的脚本:
|
|
Often, we will want to check to see if we have comand line arguments on which to act. There are a couple of ways to do this. First, we could simply check to see if $1
contains anything like so:
通常,我们需要检查是否有命令行参数可供操作。有几种方法可以做到这一点。首先,我们可以简单地检查$1
是否包含任何内容,例如:
|
|
Second, the shell maintains a variable called $#
that contains the number of items on the command line in addition to the name of the command ($0
).
其次,Shell维护一个名为$#
的变量,其中包含命令行上的项目数,以及命令的名称($0
)。
|
|
As we discussed before, many programs, particularly ones from the GNU Project, support both short and long command line options. For example, to display a help message for many of these programs, we may use either the “-h
” option or the longer “--help
” option. Long option names are typically preceded by a double dash. We will adopt this convention for our scripts.
如前所述,许多程序,特别是来自GNU项目的程序,支持短选项和长选项。例如,要显示许多这些程序的帮助消息,我们可以使用"-h
“选项或更长的”--help
“选项。长选项名称通常以两个连字符开头。我们将采用这种约定来编写我们的脚本。
Here is the code we will use to process our command line:
以下是我们将用于处理命令行的代码:
|
|
This code is a little tricky, so we need to explain it.
这段代码有点复杂,所以我们需要解释一下。
The first two lines are pretty easy. We set the variable interactive
to be empty. This will indicate that the interactive mode has not been requested. Then we set the variable filename
to contain a default file name. If nothing else is specified on the command line, this file name will be used.
前两行很简单。我们将变量interactive
设置为空。这表示未请求交互模式。然后我们设置变量filename
包含默认文件名。如果在命令行上没有指定其他内容,将使用此文件名。
After these two variables are set, we have default settings, in case the user does not specify any options.
设置这两个变量后,我们有了默认设置,以防用户未指定任何选项。
Next, we construct a while
loop that will cycle through all the items on the command line and process each one with case
. The case
will detect each possible option and process it accordingly.
接下来,我们构建一个while
循环,将循环遍历命令行上的所有项目,并使用case
处理每个项目。case
将检测每个可能的选项并相应地处理它。
Now the tricky part. How does that loop work? It relies on the magic of shift
.
现在是棘手的部分。这个循环是如何工作的?它依赖于shift
的魔力。
shift
is a shell builtin that operates on the positional parameters. Each time we invoke shift
, it “shifts” all the positional parameters down by one. $2
becomes $1
, $3
becomes $2
, $4
becomes $3
, and so on. Try this:
shift
是一个Shell内置命令,用于操作位置参数。每次我们调用shift
时,它会将所有位置参数向下“移动”一位。$2
变为$1
,$3
变为$2
,$4
变为$3
,依此类推。请试试这个:
|
|
Our “-f
” option requires a valid file name as an argument. We use shift
again to get the next item from the command line and assign it to filename
. Later we will have to check the content of filename
to make sure it is valid.
我们的”-f
“选项需要一个有效的文件名作为参数。我们再次使用shift
从命令行中获取下一个项目,并将其赋给filename
。稍后,我们将需要检查filename
的内容,以确保它是有效的。
We will have to move a few things around and add a usage function to get this new routine integrated into our script. We’ll also add some test code to verify that the command line processor is working correctly. Our script now looks like this:
我们需要移动一些内容并添加一个usage函数来将这个新例程集成到我们的脚本中。我们还将添加一些测试代码来验证命令行处理器是否正常工作。我们的脚本现在如下所示:
|
|
The interactive mode is implemented with the following code:
交互模式使用以下代码实现:
|
|
First, we check if the interactive mode is on, otherwise we don’t have anything to do. Next, we ask the user for the file name. Notice the way the prompt is worded:
首先,我们检查交互模式是否打开,否则我们没有任何事情要做。接下来,我们要求用户输入文件名。注意提示的方式:
|
|
We display the current value of filename
since, the way this routine is coded, if the user just presses the enter key, the default value of filename
will be used. This is accomplished in the next two lines where the value of response
is checked. If response
is not empty, then filename
is assigned the value of response
. Otherwise, filename
is left unchanged, preserving its default value.
我们显示filename
的当前值,因为按下回车键时,如果用户没有输入任何内容,则将使用filename
的默认值。在下面两行中,检查response
的值。如果response
不为空,则将filename
赋值为response
的值。否则,保持filename
不变,保留其默认值。
After we have the name of the output file, we check if it already exists. If it does, we prompt the user. If the user response is not “y,” we give up and exit, otherwise we can proceed.
在获得输出文件的名称后,我们检查它是否已经存在。如果存在,我们会提示用户。如果用户响应不是"y”,我们放弃并退出,否则我们可以继续。