Jak Mogę połączyć elementy tablicy w Bash?

Jeśli mam taką tablicę w Bash:

FOO=( a b c )

Jak połączyć elementy przecinkami? Na przykład produkcja a,b,c.

 459
Author: Benjamin W., 2009-10-06

30 answers

100% Czysta funkcja Bash, która obsługuje ograniczniki wielu znaków to:

function join_by { local d=$1; shift; local f=$1; shift; printf %s "$f" "${@/#/$d}"; }

Na przykład,

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
join_by '-n' '-e' '-E' '-n' #-e-n-E-n-n
join_by , #
join_by , a #a

Powyższy kod jest oparty na pomysłach @ gniourf_gniourf, @ AdamKatz i @MattCowell.

Alternatywnie, prostszą funkcją, która obsługuje tylko pojedynczy ogranicznik znaków, będzie:

function join_by { local IFS="$1"; shift; echo "$*"; }

Na przykład,

join_by , a "b c" d #a,b c,d
join_by / var local tmp #var/local/tmp
join_by , "${FOO[@]}" #a,b,c

To rozwiązanie jest oparte na oryginalnej sugestii Pascala Pilza.

Szczegółowe wyjaśnienie proponowanych tu rozwiązań można znaleźć w "Jak dołączyć() elementy tablicy w skrypcie bash", Artykuł meleu W dev.to.

 626
Author: Nicholas Sushkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-06 23:37:13

Yet another solution:

#!/bin/bash
foo=('foo bar' 'foo baz' 'bar baz')
bar=$(printf ",%s" "${foo[@]}")
bar=${bar:1}

echo $bar

Edit: to samo, ale dla wielo-znakowego separatora o zmiennej długości:

#!/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
 216
Author: doesn't matters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-05 11:08:57
$ foo=(a "b c" d)
$ bar=$(IFS=, ; echo "${foo[*]}")
$ echo "$bar"
a,b c,d
 161
Author: Pascal Pilz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-18 15:56:47

Może, np.

SAVE_IFS="$IFS"
IFS=","
FOOJOIN="${FOO[*]}"
IFS="$SAVE_IFS"

echo "$FOOJOIN"
 70
Author: martin clayton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-15 10:35:30

O dziwo moje rozwiązanie nie zostało jeszcze podane :) to dla mnie najprostszy sposób. Nie potrzebuje funkcji:

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

Uwaga: zaobserwowano, że rozwiązanie to działa dobrze w trybie non-POSIX. W trybie POSIX elementy są nadal prawidłowo połączone, ale IFS=, stają się trwałe.

 34
Author: konsolebox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-15 15:03:21

Oto 100% Czysta funkcja Bash, która wykonuje zadanie:

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

Look:

$ 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


$

To zachowuje nawet kończące się linie nowe i nie potrzebuje podshell, aby uzyskać wynik funkcji. Jeśli nie lubisz printf -v (Dlaczego nie lubisz?) i przekazując nazwę zmiennej, możesz oczywiście użyć zmiennej globalnej dla zwracanego ciągu znaków:

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}"
}
 23
Author: gniourf_gniourf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-15 09:11:22

To nie różni się zbytnio od istniejących rozwiązań, ale unika użycia oddzielnej funkcji, nie modyfikuje IFS w powłoce nadrzędnej i wszystko jest w jednej linii:

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

W wyniku

a,b,c

Ograniczenie: separator nie może być dłuższy niż jeden znak.

 22
Author: Benjamin W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-08 17:35:56

Brak zewnętrznych poleceń:

$ 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

Uwaga, zakłada, że elementy nie mają spacji.

 21
Author: Nil Geisweiller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-06 22:16:51

Chciałbym echo tablicy jako ciąg znaków, następnie przekształcić spacje w kanały linii, a następnie użyć paste, aby połączyć wszystko w jednej linii, jak tak:

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

Wyniki:

a,b,c

To wydaje mi się najszybsze i najczystsze !
 14
Author: Yanick Girouard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-06 20:49:49

Z re-use @ doesn' t matters ' solution, ale z jednym poleceniem unikając $ {: 1} substytucji i potrzeby zmiennej pośredniczącej.

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

Printf ma ' ciąg formatujący jest używany tak często, jak to konieczne, aby spełnić argumenty.'na jego stronach podręcznika, tak aby konkatenacje łańcuchów były udokumentowane. Następnie sztuczka polega na użyciu długości listy, aby posiekać ostatni sperator, ponieważ cut zachowa tylko długość listy, jak liczą się pola.

 9
Author: Valise,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-04 14:46:10
s=$(IFS=, eval 'echo "${FOO[*]}"')
 7
Author: eel ghEEz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-26 09:18:54

Rozwiązanie Printf akceptujące separatory o dowolnej długości (na podstawie odpowiedzi @doesn ' t matters)

#/!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
 6
Author: Riccardo Galli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-05 10:35:26

Krótsza wersja top odpowiedzi:

joinStrings() { local a=("${@:3}"); printf "%s" "$2${a[@]/#/$1}"; }

Użycie:

joinStrings "$myDelimiter" "${myArray[@]}"
 6
Author: Camilo Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-11 01:33:49
$ set a 'b c' d

$ history -p "$@" | paste -sd,
a,b c,d
 4
Author: Steven Penny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 03:02:27

Połącz najlepsze ze wszystkich światów do tej pory z następującym pomysłem.

# join with separator
join_ws()  { local IFS=; local s="${*/#/$1}"; echo "${s#"$1$1$1"}"; }

To małe arcydzieło jest

  • 100% pure bash (rozszerzenie parametrów z IFS tymczasowo wyłączone, brak wywołań zewnętrznych, brak printf ... )
  • Kompaktowy, kompletny i bezbłędny (współpracuje z ogranicznikami jedno - i wielo-znakowymi, współpracuje z ogranicznikami zawierającymi białe spacje, podziały linii i inne specjalne znaki powłoki, współpracuje z pustym ogranicznikiem)
  • efficient ( no subshell, no array copy )
  • Proste i głupie, do pewnego stopnia piękne i pouczające.]}

Przykłady:

$ 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
 4
Author: guest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-19 22:17:30

Dzięki @ gniourf_gniourf za szczegółowe komentarze na temat mojej kombinacji najlepszych światów do tej pory. Przepraszamy za zamieszczenie kodu nie dokładnie zaprojektowanego i przetestowanego. Tutaj jest lepsza próba.

# join with separator
join_ws() { local d=$1 s=$2; shift 2 && printf %s "$s${@/#/$d}"; }

To piękno przez poczęcie jest

  • (nadal) 100% czysty bash (dzięki za wyraźne wskazanie, że printf jest również wbudowany. Nie wiedziałem o tym wcześniej ... )
  • działa z ogranicznikami wielu znaków
  • Bardziej kompaktowy i pełniejszy. tym razem starannie przemyślany i długoterminowe testy z losowymi podciągami ze skryptów powłoki, obejmujące użycie specjalnych znaków powłoki lub znaków sterujących lub brak znaków w obu separatorach i / lub parametrach, i przypadki krawędzi, i przypadki narożników i inne spory, jak brak argumentów w ogóle. To nie gwarantuje, że nie będzie więcej błędów, ale znalezienie takiego będzie trudniejsze. BTW, nawet aktualnie najwyżej głosowane odpowiedzi i pokrewne cierpią na takie rzeczy-e bug ...

Dodatkowe przykłady:

$ 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 $ 
$
 4
Author: guest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-22 00:44:17

Oto pojedynczy liner, który jest trochę dziwny, ale działa dobrze dla ograniczników wielu znaków i obsługuje dowolną wartość (w tym zawierające spacje lub cokolwiek):

ar=(abc "foo bar" 456)
delim=" | "
printf "%s\n$delim\n" "${ar[@]}" | head -n-1 | paste -sd ''

Będzie to widoczne w konsoli jako

abc | foo bar | 456

Uwaga: zauważ, jak niektóre rozwiązania używają printf z ${ar[*]}, a niektóre z ${ar[@]}?

Te z @ używają funkcji printf, która obsługuje wiele argumentów, powtarzając szablon formatu.

Te z * nie powinno być używany . W rzeczywistości nie potrzebują printf i polegają na manipulowaniu separatorem pól i rozszerzaniu słowa Basha. Sprawdziłyby się równie dobrze z echo, cat, itd. - te rozwiązania prawdopodobnie używają printf, ponieważ autor nie do końca rozumie, co robią...

 3
Author: Guss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-20 15:05:18

x=${"${arr[*]}"// /,}

To najkrótsza droga.

Przykład,

arr=(1 2 3 4 5)
x=${"${arr[*]}"// /,}
echo $x  # output: 1,2,3,4,5
 2
Author: user31986,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-12 05:29:49

Teraz używam:

TO_IGNORE=(
    E201 # Whitespace after '('
    E301 # Expected N blank lines, found M
    E303 # Too many blank lines (pep8 gets confused by comments)
)
ARGS="--ignore `echo ${TO_IGNORE[@]} | tr ' ' ','`"

Który działa, ale (w ogólnym przypadku) będzie się strasznie łamał, jeśli elementy tablicy mają w sobie spację.

(dla zainteresowanych jest to skrypt wrappera wokół pep8.py )

 1
Author: David Wolever,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-07 05:13:35

Moja próba.

$ array=(one two "three four" five)
$ echo "${array[0]}$(printf " SEP %s" "${array[@]:1}")"
one SEP two SEP three four SEP five
 1
Author: Ben Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-15 03:28:52

Użyj Perla dla separatorów wielocharakterystycznych:

function join {
   perl -e '$s = shift @ARGV; print join($s, @ARGV);' "$@"; 
}

join ', ' a b c # a, b, c

Lub w jednym wierszu:

perl -le 'print join(shift, @ARGV);' ', ' 1 2 3
1, 2, 3
 1
Author: Daniel Patru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-13 18:55:43

Jeśli zbudujesz tablicę w pętli, Oto prosty sposób:

arr=()
for x in $(some_cmd); do
   arr+=($x,)
done
arr[-1]=${arr[-1]%,}
echo ${arr[*]}
 1
Author: Ian Kelling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-08 23:50:44

Jeśli elementy, które chcesz połączyć, nie są tablicą, tylko oddzielonym spacjami łańcuchem, możesz zrobić coś takiego:

foo="aa bb cc dd"
bar=`for i in $foo; do printf ",'%s'" $i; done`
bar=${bar:1}
echo $bar
    'aa','bb','cc','dd'

Na przykład, mój przypadek użycia polega na tym, że niektóre łańcuchy są przekazywane w moim skrypcie powłoki i muszę użyć tego do uruchomienia na zapytaniu SQL:

./my_script "aa bb cc dd"

W my_script, muszę zrobić " SELECT * FROM table WHERE name IN ('aa','bb','CC','dd'). Wtedy powyższe polecenie będzie przydatne.

 1
Author: Dexin Wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-29 17:12:00

Użycie zmiennej indirection do bezpośredniego odniesienia się do tablicy również działa. Można również używać nazw odwołań, ale stały się one dostępne dopiero w 4.3.

Zaletą użycia tej formy funkcji jest to, że możesz mieć separator opcjonalny (domyślnie pierwszy znak IFS, który jest spacją; być może uczynić go pustym łańcuchem, jeśli chcesz), a to pozwala uniknąć dwukrotnego rozszerzania wartości (pierwszy przekazywany jako parametry, a drugi jako "$@" wewnątrz funkcji).

To rozwiązanie nie wymaga również od użytkownika wywołania funkcji wewnątrz polecenia substitution-które przywołuje subshell, aby uzyskać połączoną wersję łańcucha przypisanego do innej zmiennej.

function join_by_ref {
    __=
    local __r=$1[@] __s=${2-' '}
    printf -v __ "${__s//\%/%%}%s" "${!__r}"
    __=${__:${#__s}}
}

array=(1 2 3 4)

join_by_ref array
echo "$__" # Prints '1 2 3 4'.

join_by_ref array '%s'
echo "$__" # Prints '1%s2%s3%s4'.

join_by_ref 'invalid*' '%s' # Bash 4.4 shows "invalid*[@]: bad substitution".
echo "$__" # Prints nothing but newline.

Możesz użyć wygodniejszej nazwy dla funkcji.

To działa od 3.1 do 5.0-Alfa. Jak zaobserwowano, indirection zmiennych nie działa tylko ze zmiennymi, ale także z innymi parametrami.

Parametr jest jednostką, która przechowuje wartości. Może to być imię, a numer lub jeden ze znaków specjalnych wymienionych poniżej w sekcji specjalne Parametry. Zmienna jest parametrem oznaczonym nazwą.

Tablice i elementy tablicy są również parametrami (encjami, które przechowują wartość), a odniesienia do tablic są również technicznie odniesieniami do parametrów. I podobnie jak specjalny parametr @, array[@] również stanowi ważne odniesienie.

Zmienione lub selektywne formy ekspansji (np. ekspansja podciągu), które odbiegają od parametru sama już nie działa.

Update

W wersji Release Bash 5.0, zmienna indirection jest już nazywana ekspansją pośrednią , a jej zachowanie jest już wyraźnie udokumentowane w podręczniku:

Jeśli pierwszy znak parametru jest wykrzyknikiem (!), oraz parametr nie jest nameref, wprowadza poziom indrection. Bash używa wartości utworzonej przez rozszerzenie reszty parametru jako nowy parametr; jest to następnie rozszerzony i ta wartość jest używana w reszta rozszerzenia, a nie rozszerzenie oryginału parametr. Jest to znane jako ekspansja pośrednia.

Biorąc pod uwagę, że w dokumentacji ${parameter}, parameter jest określany jako "parametr powłoki opisany (w) parametrach lub odniesienie do tablicy ". W dokumentacji tablic jest wspomniane, że "każdy element tablicy może być odwołany za pomocą ${name[subscript]}". to sprawia, że __r[@] odniesienie do tablicy.

Join by arguments version

Zobacz mój komentarz w odpowiedź Riccardo Galli.

 1
Author: konsolebox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-04 07:16:30

Wiele, jeśli nie większość, tych rozwiązań opiera się na tajemnej składni, podstępnych regexach lub wywołaniach zewnętrznych plików wykonywalnych. Chciałbym zaproponować proste, tylko bash rozwiązanie, które jest bardzo łatwe do zrozumienia, i tylko nieco poniżej optymalnego, pod względem wydajności.

join_by () {
    # Argument #1 is the separator. It can be multi-character.
    # Argument #2, 3, and so on, are the elements to be joined.
    # Usage: join_by ", " "${array[@]}"
    local SEPARATOR="$1"
    shift

    local F=0
    for x in "$@"
    do
        if [[ F -eq 1 ]]
        then
            echo -n "$SEPARATOR"
        else
            F=1
        fi
        echo -n "$x"
    done
    echo
}

Przykład:

$ a=( 1 "2 2" 3 )
$ join_by ", " "${a[@]}"
1, 2 2, 3
$ 

Chciałbym zwrócić uwagę, że każde rozwiązanie, które używa /usr/bin/[ lub /usr/bin/printf jest z natury wolniejsze niż moje rozwiązanie, ponieważ używam 100% czystego Basha. Jako przykład jego wykonania, oto demo, w którym Utwórz tablicę z 1 000 000 losowych liczb całkowitych, następnie połącz je wszystkie przecinkami i zmierz czas.

$ eval $(echo -n "a=("; x=0 ; while [[ x -lt 1000000 ]]; do echo -n " $RANDOM" ; x=$((x+1)); done; echo " )")
$ time join_by , ${a[@]} >/dev/null
real    0m8.590s
user    0m8.591s
sys     0m0.000s
$ 
 1
Author: Mark Pettit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-17 21:13:27

To podejście zajmuje się przestrzeniami w wartościach, ale wymaga pętli:

#!/bin/bash

FOO=( a b c )
BAR=""

for index in ${!FOO[*]}
do
    BAR="$BAR,${FOO[$index]}"
done
echo ${BAR:1}
 0
Author: dengel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-07 00:53:44

Oto jeden, który obsługuje większość powłok zgodnych z POSIX:

join_by() {
    # Usage:  join_by "||" a b c d
    local arg arr=() sep="$1"
    shift
    for arg in "$@"; do
        if [ 0 -lt "${#arr[@]}" ]; then
            arr+=("${sep}")
        fi
        arr+=("${arg}") || break
    done
    printf "%s" "${arr[@]}"
}
 0
Author: user541686,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-16 07:38:21

Może spóźnię się na imprezę, ale to mi pasuje:

function joinArray() {
  local delimiter="${1}"
  local output="${2}"
  for param in ${@:3}; do
    output="${output}${delimiter}${param}"
  done

  echo "${output}"
}
 0
Author: TacB0sS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-18 19:43:49

Być może brakuje mi czegoś oczywistego, ponieważ jestem nowicjuszem w całej sprawie bash / zsh,ale wygląda na to, że w ogóle nie musisz używać printf. Bez tego nie robi się naprawdę brzydko.

join() {
  separator=$1
  arr=$*
  arr=${arr:2} # throw away separator and following space
  arr=${arr// /$separator}
}

Przynajmniej, to działa dla mnie do tej pory bez problemu.

Na przykład, join \| *.sh, który, powiedzmy, że jestem w moim katalogu ~, wychodzi utilities.sh|play.sh|foobar.sh. Dla mnie Wystarczy.

EDIT: jest to w zasadzie odpowiedź Nila Geisweillera , ale uogólniona na funkcję.

 -1
Author: Jordan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:34
liststr=""
for item in list
do
    liststr=$item,$liststr
done
LEN=`expr length $liststr`
LEN=`expr $LEN - 1`
liststr=${liststr:0:$LEN}

To zajmuje się również dodatkowym przecinkiem na końcu. Nie jestem ekspertem od Basha. Tylko moje 2C, ponieważ jest to bardziej elementarne i zrozumiałe

 -2
Author: byte_array,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-26 02:00:56