如果我在Bash中有这样的数组:
FOO=( a b c )
Run Code Online (Sandbox Code Playgroud)
如何用逗号连接元素?例如,生产a,b,c
.
Nic*_*kin 505
Pascal Pilz将重写解决方案作为100%纯Bash中的函数(无外部命令):
function join_by { local IFS="$1"; shift; echo "$*"; }
Run Code Online (Sandbox Code Playgroud)
例如,
join_by , a "b c" d #a,b c,d
join_by / var local tmp #var/local/tmp
join_by , "${FOO[@]}" #a,b,c
Run Code Online (Sandbox Code Playgroud)
或者,我们可以使用printf来支持多字符分隔符,使用@gniourf_gniourf的想法
function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
Run Code Online (Sandbox Code Playgroud)
例如,
join_by , a b c #a,b,c
join_by ' , ' a b c #a , b , c
join_by ')|(' a b c #a)|(b)|(c
join_by ' %s ' a b c #a %s b %s c
join_by $'\n' a b c #a<newline>b<newline>c
join_by - a b c #a-b-c
join_by '\' a b c #a\b\c
Run Code Online (Sandbox Code Playgroud)
小智 199
又一个解决方案:
#!/bin/bash
foo=('foo bar' 'foo baz' 'bar baz')
bar=$(printf ",%s" "${foo[@]}")
bar=${bar:1}
echo $bar
Run Code Online (Sandbox Code Playgroud)
编辑:相同但对于多字符可变长度分隔符:
#!/bin/bash
separator=")|(" # e.g. constructing regex, pray it does not contain %s
foo=('foo bar' 'foo baz' 'bar baz')
regex="$( printf "${separator}%s" "${foo[@]}" )"
regex="${regex:${#separator}}" # remove leading separator
echo "${regex}"
# Prints: foo bar)|(foo baz)|(bar baz
Run Code Online (Sandbox Code Playgroud)
小智 129
$ foo=(a "b c" d)
$ bar=$(IFS=, ; echo "${foo[*]}")
$ echo "$bar"
a,b c,d
Run Code Online (Sandbox Code Playgroud)
mar*_*ton 65
也许,例如,
SAVE_IFS="$IFS"
IFS=","
FOOJOIN="${FOO[*]}"
IFS="$SAVE_IFS"
echo "$FOOJOIN"
Run Code Online (Sandbox Code Playgroud)
kon*_*box 27
令人惊讶的是我的解决方案尚未给出:)这对我来说是最简单的方法.它不需要功能:
IFS=, eval 'joined="${foo[*]}"'
Run Code Online (Sandbox Code Playgroud)
注意:观察到此解决方案在非POSIX模式下运行良好.在POSIX模式下,元素仍然正确连接,但IFS=,
变为永久性.
gni*_*urf 23
这是一个完成工作的100%纯Bash功能:
join() {
# $1 is return variable name
# $2 is sep
# $3... are the elements to join
local retname=$1 sep=$2 ret=$3
shift 3 || shift $(($#))
printf -v "$retname" "%s" "$ret${@/#/$sep}"
}
Run Code Online (Sandbox Code Playgroud)
看:
$ a=( one two "three three" four five )
$ join joineda " and " "${a[@]}"
$ echo "$joineda"
one and two and three three and four and five
$ join joinedb randomsep "only one element"
$ echo "$joinedb"
only one element
$ join joinedc randomsep
$ echo "$joinedc"
$ a=( $' stuff with\nnewlines\n' $'and trailing newlines\n\n' )
$ join joineda $'a sep with\nnewlines\n' "${a[@]}"
$ echo "$joineda"
stuff with
newlines
a sep with
newlines
and trailing newlines
$
Run Code Online (Sandbox Code Playgroud)
这甚至保留了尾随换行符,并且不需要子shell来获取函数的结果.如果您不喜欢printf -v
(为什么不喜欢它?)并传递变量名,您当然可以为返回的字符串使用全局变量:
join() {
# $1 is sep
# $2... are the elements to join
# return is in global variable join_ret
local sep=$1 IFS=
join_ret=$2
shift 2 || shift $(($#))
join_ret+="${*/#/$sep}"
}
Run Code Online (Sandbox Code Playgroud)
Ben*_* W. 13
这与现有解决方案并没有太大不同,但是它避免使用单独的函数,不在IFS
父外壳中进行修改,并且全部在一行中:
arr=(a b c)
printf '%s\n' "$(IFS=,; printf '%s' "${arr[*]}")"
Run Code Online (Sandbox Code Playgroud)
导致
a,b,c
Run Code Online (Sandbox Code Playgroud)
限制:分隔符不能超过一个字符。
Yan*_*ard 12
我会将数组作为字符串回显,然后将空格转换为换行符,然后用于paste
将所有内容连接到一行中,如下所示:
tr " " "\n" <<< "$FOO" | paste -sd , -
结果:
a,b,c
这对我来说似乎是最快最干净的!
use*_*986 10
x=${arr[*]// /,}
这是最短的方法。
例子,
# ZSH:
arr=(1 "2 3" 4 5)
x=${"${arr[*]}"// /,}
echo $x # output: 1,2,3,4,5
# ZSH/BASH:
arr=(1 "2 3" 4 5)
a=${arr[*]}
x=${a// /,}
echo $x # output: 1,2,3,4,5
Run Code Online (Sandbox Code Playgroud)
不使用外部命令:
$ 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
Run Code Online (Sandbox Code Playgroud)
警告,它假定元素没有空格.
小智 8
重用@并不重要的解决方案,但通过避免$ {:1}替换和需要中间变量的一个声明.
echo $(printf "%s," "${LIST[@]}" | cut -d "," -f 1-${#LIST[@]} )
Run Code Online (Sandbox Code Playgroud)
printf has'格式字符串经常被重用,以满足参数.' 在其手册页中,以便记录字符串的连接.然后诀窍是使用LIST长度来切割最后一个sperator,因为cut将仅保留LIST的长度作为字段计数.
s=$(IFS=, eval 'echo "${FOO[*]}"')
Run Code Online (Sandbox Code Playgroud)
最佳答案的简短版本:
joinStrings() { local a=("${@:3}"); printf "%s" "$2${a[@]/#/$1}"; }
Run Code Online (Sandbox Code Playgroud)
用法:
joinStrings "$myDelimiter" "${myArray[@]}"
Run Code Online (Sandbox Code Playgroud)
可以接受任意长度分隔符的printf解决方案(基于@无关紧要的答案)
#/!bin/bash
foo=('foo bar' 'foo baz' 'bar baz')
sep=',' # can be of any length
bar=$(printf "${sep}%s" "${foo[@]}")
bar=${bar:${#sep}}
echo $bar
Run Code Online (Sandbox Code Playgroud)
小智 5
感谢 @gniourf_gniourf 对我迄今为止最好的世界组合的详细评论。很抱歉发布没有经过彻底设计和测试的代码。这是一个更好的尝试。
# join with separator
join_ws() { local d=$1 s=$2; shift 2 && printf %s "$s${@/#/$d}"; }
Run Code Online (Sandbox Code Playgroud)
这种受孕之美是
附加示例:
$ 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 $
$
Run Code Online (Sandbox Code Playgroud)