我正在尝试实现这个 helper bash 功能:
ores_simple_push(){(
set -eo pipefail
git add .
git add -A
args=("$@")
if [[ ${#args[@]} -lt 1 ]]; then
args+=('squash-this-commit')
fi
git commit -am "'${args[@]}'" || { echo; }
git push
)}
Run Code Online (Sandbox Code Playgroud)
with: git commit -am 'some stuff here',我真的不喜欢输入引号,所以我想做:
ores_simple_push my git commit message here gets put into a single string
Run Code Online (Sandbox Code Playgroud)
所以这将变成:
git commit -am 'my git commit message here gets put into a single string'
Run Code Online (Sandbox Code Playgroud)
有没有一种理智的方法来做到这一点?
在类似 Korn/POSIX 的 shell 中,while"$@"扩展为所有位置参数,分隔(在列表上下文中),"$*"扩展为位置参数与$IFS¹的第一个字符(带有某些 shell 的字节)或 SPC 如果$IFS未设置或如果$IFS没有设置为空字符串。
而在ksh/ zsh/ bash/ yash(支持数组的类似 Bourne 的 shell)中,"${array[@]}"vs 也是如此"${array[*]}"。
在zsh,"$array"是一样的"${array[*]}",而在ksh/ bash,这是一样的"${array[0]}"。在 中yash,这与 相同"${array[@]}"。
在 中zsh,您可以使用j参数扩展标志将具有任意分隔符的数组元素"${(j[ ])array}"连接起来:例如在空间上连接。它不仅限于单个字符/字节字符串,"${(j[ and ])array}"例如,您还可以使用p参数扩展标志来在分隔符规范中使用转义序列或变量(例如"${(pj[\t])array}"加入制表符并"${(pj[$var])array}"加入 的内容$var)。另请参阅F快捷标志(与 相同pj[\n])以加入换行符。
所以在这里:
ores_simple_push() (
set -o errexit -o pipefail
git add .
git add -A
args=("$@")
if [[ ${#args[@]} -lt 1 ]]; then
args+=('squash-this-commit')
fi
IFS=' '
git commit -am "${args[*]}" || true
git push
)
Run Code Online (Sandbox Code Playgroud)
或者只是POSIXly:
ores_simple_push() (
set -o errexit
git add .
git add -A
[ "$#" -gt 0 ] || set square-this-commit
IFS=' '
git commit -am "$*" || true
git push
)
Run Code Online (Sandbox Code Playgroud)
对于某些 shell(包括 bash、ksh93、mksh 和 bosh,但不包括 dash、zsh 或 yash),您还可以使用 "${*-square-this-commit}"在此处。
为了完整bash起见,将数组与任意字符串连接起来(相当于 zsh's joined=${(ps[$sep])array}),您可以执行以下操作:
IFS=
joined="${array[*]/#/$sep}"
joined=${joined#"$sep"}
Run Code Online (Sandbox Code Playgroud)
(假设$sep是区域设置中的有效文本;如果不是,则如果内容$sep与其余内容连接时最终形成有效文本,则第二步可能会失败)。
¹ 作为历史记录,在 Bourne shell 中,无论 $IFS