我可以写
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
Run Code Online (Sandbox Code Playgroud)
最终结果对我来说似乎都差不多。我为什么要写一个或另一个?这些中的任何一个都不是便携式/ POSIX 吗?
过去的旧建议是对任何涉及 a 的表达式加双引号$VARIABLE,至少在希望 shell 将其解释为单个项目的情况下,否则,内容中的任何空格$VARIABLE都会脱离 shell。
但是,我知道在较新版本的 shell 中,不再总是需要双引号(至少出于上述目的)。例如,在bash:
% FOO='bar baz'
% [ $FOO = 'bar baz' ] && echo OK
bash: [: too many arguments
% [[ $FOO = 'bar baz' ]] && echo OK
OK
% touch 'bar baz'
% ls $FOO
ls: cannot access bar: No such file or directory
ls: cannot access baz: No such file or directory
Run Code Online (Sandbox Code Playgroud)
在zsh,而另一方面,同样的三个命令成功。因此,基于此实验,似乎在 中bash可以省略 内部的双引号[[ ... ]],但不能省略内部 …
我可以安全地省略本地作业右侧的引号吗?
function foo {
local myvar=${bar}
stuff()
}
Run Code Online (Sandbox Code Playgroud)
我主要对 感兴趣bash,但欢迎提供有关其他 shell 中的边角案例的任何信息。
在我的 GNU bash 版本 4.2.8 中,IFS 默认有空格、制表符和换行符的默认值:
usr@T42 ~ $ echo -n "$IFS" | hexdump -C
00000000 20 09 0a | ..|
00000003
usr@T42 ~ $
Run Code Online (Sandbox Code Playgroud)
是否有这种默认 IFS 的原因?此外,除了内置 bash 之外,还有哪些实用程序使用 IFS read?
即使将其输出分配给变量,我也倾向于引用如下所示的命令替换:
var="$(command)"
Run Code Online (Sandbox Code Playgroud)
但这真的需要吗?什么时候断?此处接受的答案声称:
DIRNAME = “$(目录名称$ FILE)”不会做你想做的,如果$文件包含空格或的通配符[?*。
该链接指向 Gray Cat Wiki 关于引用的精彩页面,但该页面没有特别提及引用命令替换。虽然显然需要引用变量,但引用命令替换本身似乎并不需要。
然而,同一篇文章的结尾是:
DIRNAME="$(dirname "$FILE")" 是推荐的方式。您可以用命令和空格替换 DIRNAME= 而不更改任何其他内容,并且 dirname 接收正确的字符串。
这也是我一直以来的想法,并且经常在这里修改没有引用它的帖子。但是,链接到上面的维基页面也声称:
有几种情况可以安全地省略双引号:
在简单作业的右侧。你可以写 foo=$bar 不带引号。这是符合 POSIX 的。
[. . . ]
虽然var=$(command)不是真正的“简单”任务,但我仍然无法找到实际需要引号的情况:
$ var=$(echo "foo bar baz") ## whitespace works
$ echo "$var"
foo bar baz
$ var=$(printf "foo\nbar * baz") ## so do globbing characters
$ echo "$var"
foo
bar * baz
$ var1="foo\nbar * baz"
$ var=$(printf "$var1") ## printing …Run Code Online (Sandbox Code Playgroud) 我在这里阅读了一些关于在 shell 上引用变量的答案。基本上,这就是我正在运行的内容:
for f in "$(tmsu files)"; do echo "${f}"; done
这有预期的结果:文件列表。但是,我很确定它们是作为单个字符串出现的。经过一些阅读,我意识到这是一个 zsh-ism;它处理分裂的方式与大多数贝壳不同。
所以我启动bash并运行相同的命令。我原以为它会拆分列表,但唉,我得到了完全相同的结果。所以现在我真的很困惑。
我试过 (zsh):
for f in "$(tmsu files)"; do echo "${=f}"; done
以及
for f in "$(=tmsu files)"; do echo "${f}"; done
都没有奏效,所以显然我误解了如何zsh拆分。
更糟糕的是,在某些时候,我完全按照自己的意愿去做了,但我不记得我是怎么做到的。
我想做的是获取用户输入并搜索文件,如果匹配,它将显示结果,否则它将回显 $keyword not found。
但我的票据总是返回错误。
read -p "Enter keyword: " keyword
if search="$(cat ./records | grep '$keyword')"
then
echo "$search"
else
echo "$keyword not found!"
fi ;;
Run Code Online (Sandbox Code Playgroud) 我的awk输出是多行字符串。
awkresult=`awk '{...}'`
echo "{ \"result\": \"$awkresult\" }" > result.json
Run Code Online (Sandbox Code Playgroud)
多行必须保留在结果字符串中。
我认为最好的方法是在每行末尾插入换行符awkresult。
我的awk脚本无法修改。我应该如何修改我的代码?