bash 中的命令替换声明语法 - 这两种方法中哪一种更好?

bash 中的命令替换声明语法 - 这两种方法中哪一种更好?

这是 bashfind循环的一部分,我想知道哪个语法更正确,为什么?

filename="$(echo "$i" | cut -c5-)";
filename=`echo "$i" | cut -c5-`;

两者的作用都是为了获取文件名。

答案1

Bash 手册指出:

POSIX $() 形式的命令替换已实现(请参阅命令替换),并且优于 Bourne shell 的 `` (它也是为了向后兼容而实现的)。

因此,在您正在编写的任何新的和特定于 Bash 的内容中,So$(...)是首选的。`...`反引号替换不能很好地嵌套(你必须转义它们),并且有一些稍微奇怪的引用行为。您可以$(... $(...) ...)任意嵌套,没有问题。手册将两人的行为描述为:

当使用旧式反引号形式的替换时,反斜杠保留其字面含义,除非后跟“$”、“`”或“\”。前面没有反斜杠的第一个反引号终止命令替换。当使用$(command)形式时,括号内的所有字符组成命令;没有一个受到特殊对待。

它是通常认为最佳实践是引用所有字符串扩展以避免分词问题,包括在不严格要求的地方,因此"$(...)"这里也是更好的实践。

最后,其中两个相关部分相同的羊毛边页面:

  • 你也到了忘记的时候了`...`。它与 Expansion 的语法不一致,并且如果不使用止痛药就很难嵌套。代替使用$(...)
  • 看在上帝的份上,“多用引号!”保护您的字符串和参数扩展免受分词。如果你没有正确引用的话,分词就会吃掉你的孩子。

1实际上,即使在 POSIXsh脚本中,这些也被认为是最佳实践。周围仍然有较弱的炮弹,但你会知道是否会遇到它们。

答案2

关于代码中与`...`vs无关的良好实践的评论$(...)

filename="$(echo "$i" | cut -c5-)"

至少有 4 个潜在的警告(除非有利用它们的动机,否则是次要的):

  • 您不能使用echo任意数据,因为您可能会遇到(取决于实现或环境)以反斜杠开头或包含反斜杠echo的值的问题。最好是在处理任意数据时使用(此处)。$i-printfprintf '%s\n' "$i"
  • cut大多数文本过滤实用程序不太适合处理文件路径,因为它们作用于每一个他们的输入行。所以在这里,你要去掉前 4 个字符每一个$i(换行符与文件名中的任何字符一样有效)。最好是使用filename=${i#????}(尽管您可能还想考虑$i包含少于 4 个字符的情况)。
  • 命令替换(`...`$(...))删除每一个命令输出中的尾随换行符。因此,如果$i以换行符结尾,您将在 中错过它们$filename${i#????}也可以解决这个问题。
  • cut -c5-${i#????}删除 4人物。请注意,在某些语言环境中,字符可以由多个字符组成字节。您可能需要考虑到这一点。 (另请注意GNUcut不支持多字节字符然而 (与))cut -c相同。cut -b

相关内容