585 Stimmen

Wie kann ich Elemente eines Arrays in der Bash verbinden?

Wenn ich ein Array wie dieses in Bash habe:

FOO=( a b c )

Wie verbinde ich die Elemente mit Kommas? Zum Beispiel, indem ich a,b,c .

40voto

konsolebox Punkte 66082

Überraschenderweise ist meine Lösung noch nicht gegeben :) Dies ist der einfachste Weg für mich. Es braucht keine Funktion:

IFS=, eval 'joined="${foo[*]}"'

Hinweis: Es wurde festgestellt, dass diese Lösung im Nicht-POSIX-Modus gut funktioniert. Unter POSIX-Modus sind die Elemente noch richtig verbunden, aber IFS=, dauerhaft wird.

35voto

Benjamin W. Punkte 37771

Dies unterscheidet sich nicht allzu sehr von bestehenden Lösungen, aber es vermeidet die Verwendung einer separaten Funktion, ändert nicht IFS in der übergeordneten Shell und besteht aus einer einzigen Zeile:

arr=(a b c)
printf '%s\n' "$(IFS=,; printf '%s' "${arr[*]}")"

was zu

a,b,c

Einschränkung: Das Trennzeichen darf nicht länger als ein Zeichen sein.


Dies könnte vereinfacht werden, indem man

(IFS=,; printf '%s' "${arr[*]}")

dann ist es im Grunde dasselbe wie Pascals Antwort sondern mit printf 代わりに echo und gibt das Ergebnis auf stdout aus, anstatt es einer Variablen zuzuweisen.

25voto

gniourf_gniourf Punkte 41590

Hier ist eine 100% reine Bash-Funktion, die diese Aufgabe erfüllt:

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}"
}

Sehen Sie:

$ 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

$

Dabei bleiben sogar die nachgestellten Zeilenumbrüche erhalten, und es wird keine Subshell benötigt, um das Ergebnis der Funktion zu erhalten. Wenn Sie die Funktion nicht mögen printf -v (warum auch nicht?) und Übergabe eines Variablennamens können Sie natürlich eine globale Variable für die zurückgegebene Zeichenkette verwenden:

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}"
}

20voto

Yanick Girouard Punkte 4363

Ich würde das Array als String ausgeben, dann die Leerzeichen in Zeilenvorschübe umwandeln und dann paste um alles in einer Zeile zusammenzufassen, etwa so:

tr " " "\n" <<< "$FOO" | paste -sd , -

Ergebnisse:

a,b,c

Das scheint mir die schnellste und sauberste Methode zu sein!

10voto

Valise Punkte 117

Mit Wiederverwendung der Lösung von @doesn't matters, aber mit einer einzigen Anweisung unter Vermeidung der ${:1}-Substitution und der Notwendigkeit einer Zwischenvariablen.

echo $(printf "%s," "${LIST[@]}" | cut -d "," -f 1-${#LIST[@]} )

In den Man Pages von printf steht 'The format string is reused as often as necessary to satisfy the arguments.', so dass die Verkettung der Zeichenketten dokumentiert ist. Dann besteht der Trick darin, die LIST-Länge zu verwenden, um den letzten Sperator zu zerschneiden, da cut nur die Länge von LIST als Feldanzahl beibehält.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X