带引号“$()”的变量

Sha*_*ara 13 bash scripts

我写了这个脚本:

#!/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

引号可防止“分词”。即:在空格字符处(或更确切地说,在默认$IFSshell 变量的值中定义的空格、制表符和换行符处)将变量分解为多个项目。

例如,

$ 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)

在这里,发生分词,而是[看到两个字符串helloworld然后是!=,然后是另外两个字符串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、内存使用和执行时间的成本(即使这些命令可能是从内存中预加载的)。


也可以看看:

  • @RoVo 是的,为了可移植性,应该首选 `printf`。由于我们在这里使用 bash 特定的脚本,因此可以使用 `echo`。但是你的观察非常正确 (2认同)