Bash 中变量替换中的反斜杠

Bash 中变量替换中的反斜杠

我正在编写一个 Bash 脚本来帮助正确分区硬盘驱动器,我遇到了一个奇怪的问题,我必须向变量附加一个数字。我花了一段时间才得到正确的结果,因为我对 Bash 不太有经验,但我设法做了一些临时的事情。

这是我正在构建的示例:

#!/bin/bash

devName="/dev/sda"
devTarget=$devName\3

echo "$devTarget"

变量devName/dev/sda,但我还需要稍后在脚本中为第三个分区设置一个变量,因此我使用了符号\,这让我可以将数字添加3到 中以/dev/sda生成输出/dev/sda3

尽管该\符号有效,但我只是想知道这是否是执行此类操作的正确方法。我使用它是因为在Python中它用于忽略引用等的以下字符,但我想在这种情况下做相反的事情,所以令人惊讶的是它有效。如果这不是添加变量的最佳方法,有人可以展示一个在 Bash 中执行此操作的最佳方法的示例吗?

答案1

将变量插入字符串的安全方法是使用${var_name}.例如:

#!/bin/bash

devName="/dev/sda"
devTarget="${devName}3"

echo "$devTarget"

这样 Bash 就不会怀疑要插入的变量是什么。

顺便说一句,有趣的是如何devTarget=$devName\3运作的。我不知道为什么。

答案2

$x\b其工作方式与$x"b"or"$x"b工作方式相同,引号以变量名称结尾。如果没有其他原因,我认为发生这种情况是因为当变量扩展时引号仍然存在,并且\"'变量名称中没有一个有效。

标准文本说:

单词扩展的顺序如下:

1. ...,参数扩展(参见参数扩展),...

4. 报价删除(参见报价删除)应始终最后执行。

而“引号删除”是实际删除引号字符的步骤。

但是,正如 @tomasz 所说在他们的回答中,将变量名称放在大括号内是通常的方法,因此"${x}b", 或"${devName}3"。您几乎总是想在扩展周围加上引号,请参阅什么时候需要双引号?

(不过,我想知道除了实际保留引号字符之外,是否还有其他方法可以在程序中标记带引号的字符串。)

答案3

您的脚本显示的是您正在将变量加数字写入输出。很简单,可以使用printf格式化字符串来实现:

$ devName="/dev/sda"
$ printf "%s%d\n" "$devName" 3
/dev/sda3

但正如你提到的,你需要使用脚本后面的新变量,我们还可以利用版本-v中的标志:bashprintf

$ printf -v devTarget "%s%d" "$devName" 3
$ echo "$devTarget"
/dev/sda3

此方法不适用于POSIXprintf,并且在其他 shell 中不起作用(至少 ksh 和 mksh 没有-vprintf 的标志,不确定 zhsh)。所以我们可以通过命令替换来解决这个问题:

$ devTarget=$(printf "%s3" "$devName")

但是,那接受的答案可能会更简单、更便携。

答案4

作为托马斯指出,准确指定哪些字符构成变量名的正确方法是使用大括号,例如${devName}3.

为了方便起见,Bash 允许您省略大括号,但这样做您就失去了完全明确要引用哪个变量的能力。 bash 解决这个问题的方法是采用以美元符号开头的最长的有效变量名称。变量名称以字母或下划线开头,可以包含任意数量的字母、数字或下划线,但不能包含其他字符。因此,在您的示例中$devName\3, bash 以 开头,d并查找它可以找到的最长的字母/数字/下划线字符,即devName。它将作为要使用的变量的名称。类似地,类似的东西$here-is-a-long-string-of-words会使用名为here;的变量。会是这样的${here}-is-a-long-string-of-words

之后 bash 看到\3.反斜杠是一种引用形式,它使后面的字符被正常解释,没有任何特殊含义。但3无论如何没有任何特殊含义,所以反斜杠是多余的。这个序列最终等同于单独3的序列。

相关内容