如何将“$@”或数组连接到一个字符串

Ale*_*lls 1 shell bash git

我正在尝试实现这个 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)

有没有一种理智的方法来做到这一点?

Sté*_*las 5

在类似 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