如果我在Bash中有一个这样的数组:
FOO=( a b c )
如何用逗号连接元素?例如,生成a b c。
如果我在Bash中有一个这样的数组:
FOO=( a b c )
如何用逗号连接元素?例如,生成a b c。
当前回答
也许我遗漏了一些明显的东西,因为我是bash/zsh的新手,但在我看来,您根本不需要使用printf。没有它也不会变得很难看。
join() {
separator=$1
arr=$*
arr=${arr:2} # throw away separator and following space
arr=${arr// /$separator}
}
至少,到目前为止,它对我来说是有效的。
例如,加入\| *.sh,假设我在~目录下,输出utilities.sh|play.sh|foobar.sh。对我来说足够好了。
编辑:这基本上是Nil Geisweiller的答案,但推广到一个函数。
其他回答
这里有一个单行,有点奇怪,但适用于多字符分隔符,并支持任何值(包括包含空格或任何东西):
ar=(abc "foo bar" 456)
delim=" | "
printf "%s\n$delim\n" "${ar[@]}" | head -n-1 | paste -sd ''
这将在控制台显示为
abc | foo bar | 456
注意:注意一些解决方案是如何使用${ar[*]}和${ar[@]}的printf ?
带@的使用printf特性,通过重复格式模板来支持多个参数。
带*的不应该使用。它们实际上不需要打印,而是依赖于操作字段分隔符和bash的单词展开。这些方法同样适用于echo、cat等——这些解决方案可能使用printf,因为作者并不真正理解他们在做什么……
使用perl实现多字符分隔符:
function join {
perl -e '$s = shift @ARGV; print join($s, @ARGV);' "$@";
}
join ', ' a b c # a, b, c
或者在一行中:
perl -le 'print join(shift, @ARGV);' ', ' 1 2 3
1, 2, 3
不使用外部命令:
$ FOO=( a b c ) # initialize the array
$ BAR=${FOO[@]} # create a space delimited string from array
$ BAZ=${BAR// /,} # use parameter expansion to substitute spaces with comma
$ echo $BAZ
a,b,c
警告,它假设元素没有空格。
感谢@gniourf_gniourf对我迄今为止的最佳世界组合的详细评论。很抱歉发布的代码没有完全设计和测试。这是一个更好的尝试。
# join with separator
join_ws() { local d=$1 s=$2; shift 2 && printf %s "$s${@/#/$d}"; }
这种概念上的美是
(still) 100% pure bash ( thanks for explicitly pointing out that printf is a builtin as well. I wasn't aware about this before ... ) works with multi-character delimiters more compact and more complete and this time carefully thought over and long-term stress-tested with random substrings from shell scripts amongst others, covering use of shell special characters or control characters or no characters in both separator and / or parameters, and edge cases, and corner cases and other quibbles like no arguments at all. That doesn't guarantee there is no more bug, but it will be a little harder challenge to find one. BTW, even the currently top voted answers and related suffer from such things like that -e bug ...
附加的例子:
$ join_ws '' a b c
abc
$ join_ws ':' {1,7}{A..C}
1A:1B:1C:7A:7B:7C
$ join_ws -e -e
-e
$ join_ws $'\033[F' $'\n\n\n' 1. 2. 3. $'\n\n\n\n'
3.
2.
1.
$ join_ws $
$
结合所有最好的世界到目前为止与以下的想法。
# join with separator
join_ws() { local IFS=; local s="${*/#/$1}"; echo "${s#"$1$1$1"}"; }
这个小杰作是
100%纯bash(参数扩展,暂时不设置IFS,没有外部调用,没有printf…) 紧凑、完整和完美(适用于单字符和多字符限制符,适用于包含空格、换行符和其他shell特殊字符的限制符,适用于空分隔符) 高效(无子shell,无数组复制) 简单而愚蠢,但在某种程度上,也很漂亮,很有教育意义
例子:
$ join_ws , a b c
a,b,c
$ join_ws '' a b c
abc
$ join_ws $'\n' a b c
a
b
c
$ join_ws ' \/ ' A B C
A \/ B \/ C