我写了这个脚本:
#!/bin/bash
while [ true ]
do
currentoutput="$(lsusb)"
if [ "$currentoutput" != "$lastoutput" ]
then
echo "" date and Time >> test.log
date +%x_r >> test.log
lastoutput="$(lsusb)"
lsusb >> test.log
fi
sleep 5
done
Run Code Online (Sandbox Code Playgroud)
我是一个试图快速学习的新手,我有一个关于变量引号的问题。
在 $() 之间放一个变量,我明白了,但为什么即使在语句中也需要引号if
?是要制作嵌套命令吗?
Ser*_*nyy 23
引号可防止“分词”。即:在空格字符处(或更确切地说,在默认$IFS
shell 变量的值中定义的空格、制表符和换行符处)将变量分解为多个项目。
例如,
$ var="one two"
$ howmany(){ echo $#; }
$ howmany $var
2
$ howmany "$var"
1
Run Code Online (Sandbox Code Playgroud)
这里我们定义了一个howmany
函数,它只是让我们知道给定了多少位置参数。如您所见,有两个项目被传递给变量,并且通过引号将变量中的文本视为一个单元。
这对于准确传递信息很重要。例如,如果变量包含文件路径,而文件名在路径中的任意位置包含空格,则您尝试运行的命令可能会失败或给出不准确的结果。如果我们试图用$var
变量创建一个文件,touch $var
将创建两个文件,但touch "$var"
只有一个。
你也一样[ "$currentoutput" != "$lastoutput" ]
。此特定测试对两个字符串执行比较。当测试运行时,该[
命令需要查看 3 个参数 - 一个文本字符串、!=
运算符和另一个文本字符串。保留双引号可防止分词,并且该[
命令会准确地看到这 3 个参数。现在如果变量没有被引用会发生什么?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
Run Code Online (Sandbox Code Playgroud)
在这里,发生分词,而是[
看到两个字符串hello
,world
然后是!=
,然后是另外两个字符串hi world
。关键是没有双引号,变量的内容被理解为单独的单元,而不是一个完整的项目。
分配命令替换不需要双引号
var=$( df )
Run Code Online (Sandbox Code Playgroud)
您将df
命令的输出保存到var
. 但是,始终双引号变量和命令替换是一个好习惯,$(...)
除非您确实希望将输出视为单独的项目。
附带说明一下,
while [ true ]
Run Code Online (Sandbox Code Playgroud)
部分可以
while true
Run Code Online (Sandbox Code Playgroud)
[
是一个评估其参数的命令,[ whatever ]
无论里面是什么,它总是为真。相比之下,while true
使用true
总是返回成功退出状态的命令(这正是while
循环所需要的)。不同之处在于更加清晰,并且执行的测试更少。或者,您也可以使用:
代替true
echo "" date and Time
部分双引号可能会被删除。他们只是插入一个空字符串并在输出中添加额外的空间。如果需要,请随意将它们保留在那里,但在这种情况下没有特别的功能价值。
lsusb >> test.log
Run Code Online (Sandbox Code Playgroud)
这部分可能会替换为echo "$currentoutput" >> test.log
. 没有理由来运行lsusb
它已经被运行中的后,再次currentoutput=$(lsusb)
。在
必须在输出中保留尾随换行符的情况下- 可以看到多次运行命令的值,但在lsusb
没有必要的情况下。您调用的外部命令越少越好,因为对非内置命令的每次调用都会导致 CPU、内存使用和执行时间的成本(即使这些命令可能是从内存中预加载的)。
也可以看看: