这是 bashfind
循环的一部分,我想知道哪个语法更正确,为什么?
filename="$(echo "$i" | cut -c5-)";
filename=`echo "$i" | cut -c5-`;
两者的作用都是为了获取文件名。
答案1
POSIX $() 形式的命令替换已实现(请参阅命令替换),并且优于 Bourne shell 的 `` (它也是为了向后兼容而实现的)。
因此,在您正在编写的任何新的和特定于 Bash 的内容中,So$(...)
是首选的。`...`
反引号替换不能很好地嵌套(你必须转义它们),并且有一些稍微奇怪的引用行为。您可以$(... $(...) ...)
任意嵌套,没有问题。手册将两人的行为描述为:
当使用旧式反引号形式的替换时,反斜杠保留其字面含义,除非后跟“$”、“`”或“\”。前面没有反斜杠的第一个反引号终止命令替换。当使用$(command)形式时,括号内的所有字符组成命令;没有一个受到特殊对待。
它是通常认为最佳实践是引用所有字符串扩展以避免分词问题,包括在不严格要求的地方,因此"$(...)"
这里也是更好的实践。
最后,其中两个相关部分相同的羊毛边页面:
- 你也到了忘记的时候了
`...`
。它与 Expansion 的语法不一致,并且如果不使用止痛药就很难嵌套。代替使用$(...)
。- 看在上帝的份上,“多用引号!”保护您的字符串和参数扩展免受分词。如果你没有正确引用的话,分词就会吃掉你的孩子。
1实际上,即使在 POSIXsh
脚本中,这些也被认为是最佳实践。周围仍然有较弱的炮弹,但你会知道是否会遇到它们。
答案2
关于代码中与`...`
vs无关的良好实践的评论$(...)
:
在
filename="$(echo "$i" | cut -c5-)"
至少有 4 个潜在的警告(除非有利用它们的动机,否则是次要的):
- 您不能使用
echo
任意数据,因为您可能会遇到(取决于实现或环境)以反斜杠开头或包含反斜杠echo
的值的问题。最好是在处理任意数据时使用(此处)。$i
-
printf
printf '%s\n' "$i"
cut
大多数文本过滤实用程序不太适合处理文件路径,因为它们作用于每一个他们的输入行。所以在这里,你要去掉前 4 个字符每一个行$i
(换行符与文件名中的任何字符一样有效)。最好是使用filename=${i#????}
(尽管您可能还想考虑$i
包含少于 4 个字符的情况)。- 命令替换(
`...`
或$(...)
)删除每一个命令输出中的尾随换行符。因此,如果$i
以换行符结尾,您将在 中错过它们$filename
。${i#????}
也可以解决这个问题。 cut -c5-
或${i#????}
删除 4人物。请注意,在某些语言环境中,字符可以由多个字符组成字节。您可能需要考虑到这一点。 (另请注意GNUcut
不支持多字节字符然而 (与))cut -c
相同。cut -b