我可以安全地省略本地作业右侧的引号吗?
function foo {
local myvar=${bar}
stuff()
}
Run Code Online (Sandbox Code Playgroud)
我主要对 感兴趣bash,但欢迎提供有关其他 shell 中的边角案例的任何信息。
以下变量赋值有什么区别?
var=23
var =23
var= 23
var = 23
Run Code Online (Sandbox Code Playgroud)
赋值运算符周围的空间有什么不同吗?
在 bash 脚本中,我分配了一个局部变量,以便该值取决于外部的全局环境变量 ( $MYAPP_ENV)。
if [ "$MYAPP_ENV" == "PROD" ]
then
SERVER_LOGIN=foobar123@prod.example.com
else
SERVER_LOGIN=foobar987@test.example.com
fi
Run Code Online (Sandbox Code Playgroud)
是否有更短(但干净)的方式来编写上述作业?(大概使用某种条件运算符/内联 if。)
...
_NEW_PATH=$("$_THIS_DIR/conda" ..activate "$@")
if (( $? == 0 )); then
export PATH=$_NEW_PATH
# If the string contains / it's a path
if [[ "$@" == */* ]]; then
export CONDA_DEFAULT_ENV=$(get_abs_filename "$@")
else
export CONDA_DEFAULT_ENV="$@"
fi
# ==== The next line returns an error
# ==== with the message: "export: not valid in this context /Users/avazquez/anaconda3"
export CONDA_ENV_PATH=$(get_dirname $_THIS_DIR)
if (( $("$_THIS_DIR/conda" ..changeps1) )); then
CONDA_OLD_PS1="$PS1"
PS1="($CONDA_DEFAULT_ENV)$PS1"
fi
else
return $?
fi
...
Run Code Online (Sandbox Code Playgroud)
这是为什么?我找到了这张票 …
请参阅以下示例及其在 POSIX shell 中的输出:
false;echo $?或false || echo 1:1false;foo="bar";echo $?或foo="bar" && echo 0:0foo=$(false);echo $?或foo=$(false) || echo 1:1foo=$(true);echo $?或foo=$(true) && echo 0:0正如/sf/ask/478414121/ 上投票最高的答案所提到的:
$?用于查找上次执行命令的返回值。
在这种情况下,这可能有点误导,所以让我们获取 POSIX 定义,该定义也在该线程的帖子中引用:
? 扩展到最近管道的十进制退出状态(请参阅管道)。
所以看起来好像一个赋值本身算作一个命令(或者更确切地说是一个管道部分),它的退出值为零,但它应用在赋值的右侧之前(例如,我的示例中的命令替换调用)。
从实际的角度来看,我看到这种行为是有道理的,但对我来说,作业本身按该顺序计数似乎有些不寻常。也许为了让我更清楚为什么这对我来说很奇怪,让我们假设赋值是一个函数:
ASSIGNMENT( VARIABLE, VALUE )
Run Code Online (Sandbox Code Playgroud)
那么foo="bar"将是
ASSIGNMENT( "foo", "bar" )
Run Code Online (Sandbox Code Playgroud)
并且foo=$(false)会像
ASSIGNMENT( "foo", EXECUTE( "false" ) )
Run Code Online (Sandbox Code Playgroud)
这意味着首先EXECUTE …
在许多语言中,可以将 case/switch 语句的结果赋值给变量,而不是在 case 语句中多次重复变量赋值。有没有可能在 Bash shell 中做这样的事情?
color_code=$(case "$COLOR" in
(red) 1;;
(yellow) 2;;
(green) 3;;
(blue) 4;;
esac)
Run Code Online (Sandbox Code Playgroud)
(或者,顺便说一句,在任何其他贝壳中?)
如果我这样做:
SUMAN_DEBUG=foo echo $SUMAN_DEBUG
Run Code Online (Sandbox Code Playgroud)
我没有输出
但如果我这样做:
SUMAN_DEBUG=foo && echo $SUMAN_DEBUG
Run Code Online (Sandbox Code Playgroud)
然后我得到
“富”
这是为什么?
是
x=$y
Run Code Online (Sandbox Code Playgroud)
和
x="$y"
Run Code Online (Sandbox Code Playgroud)
总是等价的?不知道如何寻找这个。到目前为止,我一直习惯于x="$y"“安全起见”。但我x=$1曾经使用过并注意到,显然,我什至不需要额外的双引号。
The Open Group POSIX 文档中定义的行为在哪里?
我在这种情况下苦苦挣扎:
$ set -- 1 2 3
$ a="$@"
$ echo "$a"
1 2 3
Run Code Online (Sandbox Code Playgroud)
我觉得出乎意料的是作业本身。
man bash关于"$@"扩展是这样说的:
当扩展发生在双引号内时,每个参数都扩展为一个单独的词。
所以这应该类似于:
b="1" "2" "3"
bash: 2: command not found
Run Code Online (Sandbox Code Playgroud)
这就是"$*"扩展的目的,我收集:
当扩展发生在双引号内时,它扩展为单个单词,每个参数的值由 IFS 特殊变量的第一个字符分隔。也就是说,“$*”等价于“$1c$2c...”,其中c是IFS变量值的第一个字符。如果未设置 IFS,则参数以空格分隔。如果 IFS 为空,则连接参数时不插入分隔符。
所以这应该是正确的:
$ set -- 1 2 3
$ a="$*"
$ echo "$a"
1 2 3
Run Code Online (Sandbox Code Playgroud)
那么为什么"$@"产量相同呢?他们应该在这一点上有所不同。这是 Bash 问题还是我的误解?
Shellcheck 将其检测为SC2124。我还可以提供一个触发SC2145的示例。
观察到:
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
4.9.0-6-amd64 #1 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 …Run Code Online (Sandbox Code Playgroud) 仅当我通过执行 触发全局扩展时,脚本的第二行才有效echo。我不明白为什么。这是命令及其执行情况以提供一些上下文。
函数定义:
~/ cat ~/.zsh/includes/ascii2gif
ascii2gif () {
setopt extendedglob
input=$(echo ${1}(:a))
_path=${input:h}
input_f=${input:t}
output_f=${${input_f}:r}.gif
cd $_path
nerdctl run --rm -v $_path:/data asciinema/asciicast2gif -s 2 -t solarized-dark $input_f $output_f
}
Run Code Online (Sandbox Code Playgroud)
激活 ascii2gif 函数的函数调试。
~/ typeset -f -t ascii2gif
Run Code Online (Sandbox Code Playgroud)
调试后的函数执行:
~/ ascii2gif ./demo.cast
+ascii2gif:1> input=+ascii2gif:1> echo /Users/b/demo.cast
+ascii2gif:1> input=/Users/b/demo.cast
+ascii2gif:2> _path=/Users/b
+ascii2gif:3> input_f=demo.cast
+ascii2gif:4> output_f=demo.gif
+ascii2gif:5> cd /Users/b
+_direnv_hook:1> trap -- '' SIGINT
+_direnv_hook:2> /Users/b/homebrew/bin//direnv export zsh
+_direnv_hook:2> eval ''
+_direnv_hook:3> trap - SIGINT
+ascii2gif:6> nerdctl run --rm …Run Code Online (Sandbox Code Playgroud) assignment ×10
bash ×4
shell ×4
shell-script ×3
variable ×3
posix ×2
zsh ×2
array ×1
case ×1
exit-status ×1
quoting ×1
scripting ×1
shellcheck ×1
string ×1
wildcards ×1