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