我正在编写一个 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
中的标志:bash
printf
$ printf -v devTarget "%s%d" "$devName" 3
$ echo "$devTarget"
/dev/sda3
此方法不适用于POSIXprintf,并且在其他 shell 中不起作用(至少 ksh 和 mksh 没有-v
printf 的标志,不确定 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
的序列。