我写了这个脚本:
#!/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
我是一名新手,想快速学习,我有一个关于变量的问题引号。
在 $() 之间放置一个变量,我明白了,但是为什么引号语句中也需要吗if
?是为了创建嵌套命令吗?
答案1
引号可防止“分词”。也就是说:在空格处(或者更准确地说,在默认$IFS
shell 变量的值中定义的空格、制表符和换行符处)将变量分解为多个项目。
例如,
$ var="one two"
$ howmany(){ echo $#; }
$ howmany $var
2
$ howmany "$var"
1
这里我们定义了一个howmany
函数,它只告诉我们给出了多少个位置参数。如您所见,有两个项目被传递给变量,并且使用引号将变量中的文本视为一个单位。
这对于准确传递信息非常重要。例如,如果变量包含文件路径,并且文件名在路径中的任何地方包含空格,则您尝试运行的命令可能会失败或给出不准确的结果。如果我们尝试使用该$var
变量创建一个文件,touch $var
则会创建两个文件,但touch "$var"
实际上只有一个。
您的部分也是如此[ "$currentoutput" != "$lastoutput" ]
。此特定测试对两个字符串进行比较。测试运行时,命令[
需要查看 3 个参数 - 一个文本字符串、!=
运算符和另一个文本字符串。保留双引号可防止分词,并且命令[
将看到这 3 个参数。现在如果变量没有加引号会发生什么?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
这里发生了单词拆分,[
看到的是两个字符串hello
和world
后跟!=
,后跟另外两个字符串hi world
。关键点是,如果没有双引号,变量的内容将被理解为单独的单元,而不是一个整体项目。
分配命令替换不需要双引号,如下所示
var=$( df )
命令df
的输出保存到。但是,除非您确实希望将输出视为单独的项目,否则var
始终对变量和命令替换使用双引号是一个好习惯。$(...)
顺便提一下,
while [ true ]
部分可以
while true
[
是一个评估其参数的命令,[ whatever ]
无论内部内容如何,它始终为真。相比之下,while true
使用始终返回成功退出状态的命令true
(这正是while
循环所需要的)。区别在于更清晰一些,执行的测试更少。或者,您也可以使用:
而不是true
部分双引号echo "" date and Time
可能可以删除。它们只是插入一个空字符串并在输出中添加额外的空格。如果需要,可以随意保留它们,但在这种情况下没有特别的功能价值。
lsusb >> test.log
这部分可能可以用 代替。在 中已经运行过后,echo "$currentoutput" >> test.log
没有理由再次运行。在以下情况下lsusb
currentoutput=$(lsusb)
尾随换行符
必须保留在输出中 - 运行命令多次可以看到值,但在这种情况下lsusb
没有必要这样做。调用的外部命令越少越好,因为每次调用非内置命令都会产生 CPU、内存使用和执行时间成本(即使命令可能是从内存中预加载的)。
也可以看看:
答案2
在currentoutput="$(lsusb)"
lsusb 中不是一个变量,它是一个命令。此语句的作用是执行lsusb
命令并将其输出赋给currentoutput
变量。
旧的语法是
currentoutput=`lsusb`
你可以在许多示例和脚本中找到它
回答你问题的另一部分,if [ ]
只是if
bash 中如何定义语法。请参阅https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
答案3
以下运行外部命令command
并返回其输出。
"$(command)"
如果没有括号/圆括号,这将查找变量而不是运行命令:
"$variable"
至于$variable
和之间的区别"$variable"
,当包含空格时,这一点很重要$variable
。使用 时"$variable"
,整个变量内容将插入到单个字符串中,即使内容中包含空格。使用 时,$variable
变量的内容可能会扩展为多个参数的参数列表。
答案4
逆势而行 - bash 建议您使用[[ ... ]]
构造[ ... ]
以避免在测试中引用变量,从而避免其他人指出的与单词拆分相关的问题。
[
在 bash 中提供 POSIX 兼容性,以便在 bash 下运行的脚本#!/bin/sh
或移植到 bash 的脚本 - 在大多数情况下,您应该避免使用它而使用[[
。
例如
# With [ - quotes are needed
$ foo='one two'; bar='one two'; [ $foo = $bar ] && echo "they're equal"
-bash: [: too many arguments
$ foo='one two'; bar='one two'; [ "$foo" = "$bar" ] && echo "they're equal"
they're equal
# versus [[ - quotes not needed
$ foo='one two'; bar='one two'; [[ $foo = $bar ]] && echo "they're equal"
they're equal