带引号的变量“$()”

带引号的变量“$()”

我写了这个脚本:

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

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

例如,

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

这里发生了单词拆分,[看到的是两个字符串helloworld后跟!=,后跟另外两个字符串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没有理由再次运行。在以下情况下lsusbcurrentoutput=$(lsusb)尾随换行符 必须保留在输出中 - 运行命令多次可以看到值,但在这种情况下lsusb没有必要这样做。调用的外部命令越少越好,因为每次调用非内置命令都会产生 CPU、内存使用和执行时间成本(即使命令可能是从内存中预加载的)。


也可以看看:

答案2

currentoutput="$(lsusb)"lsusb 中不是一个变量,它是一个命令。此语句的作用是执行lsusb命令并将其输出赋给currentoutput变量。

旧的语法是

currentoutput=`lsusb`

你可以在许多示例和脚本中找到它

回答你问题的另一部分,if [ ]只是ifbash 中如何定义语法。请参阅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

相关内容