Bashで配列の要素を結合するにはどうすればよいですか?


416

Bashにこのような配列がある場合:

FOO=( a b c )

要素をコンマで結合するにはどうすればよいですか?たとえば、を生成しa,b,cます。

回答:


571

Pascal Pilzによる100%純粋なBashの関数としてのソリューションの書き換え(外部コマンドなし):

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

例えば、

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

あるいは、@ gniourf_gniourfによるアイデアを使用して、printfを使用して複数文字の区切り文字をサポートすることもできます。

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

例えば、

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

9
これを複数文字のセパレーターに使用します:function join {perl -e '$ s = shift @ARGV; print join($ s、@ARGV); ' "$ @"; } '、' abc#a、b、cに参加する
Daniel Patru

4
@dpatruとにかくその純粋なbashを作るには?
CMCDragonkai 2014

4
@puchu機能しないのは、複数文字の区切り文字です。「スペースが機能しない」と言うと、スペースとの結合が機能しないように聞こえます。します。
Eric

6
これにより、出力を変数に保存する場合、サブシェルの生成が促進されます。konsoleboxスタイルを使用してください:) function join { local IFS=$1; __="${*:2}"; }またはfunction join { IFS=$1 eval '__="${*:2}"'; }。その後、使用__してください。はい、__結果変数としての使用を促進しているのは私です;)(および一般的な反復変数または一時変数)。コンセプトが人気のBash wikiサイトに
到達

6
$dの形式指定子に拡張を入れないでくださいprintf。あなたは「エスケープ」したので安全だと思います%が、他にも注意点があります。区切り文字にバックスラッシュが含まれている場合(例:)、\nまたは区切り文字がハイフンで始まっている場合(そして、今では考えられない他のもの)。もちろん、これらを修正することもできます(バックスラッシュを2つのバックスラッシュに置き換えて、を使用printf -- "$d%s")。そのため、以下の私の回答では、結合する用語の区切り文字を付加しました。
gniourf_gniourf 2016

206

さらに別の解決策:

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

echo $bar

編集:同じですが、複数文字の可変長セパレーターの場合:

#!/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

7
+1。どうかprintf -v bar ",%s" "${foo[@]}"。それは1つfork少なくなります(実際にはclone)。ファイルの読み取りをフォークすることもできます:printf -v bar ",%s" $(<infile)
TrueY

14
代わりに祈るの$separatorが含まれていない%sかなど、あなたが作ることができるprintf堅牢な:printf "%s%s" "$separator" "${foo[@]}"
musiphil

5
@musiphil間違い。bashのmanから:「形式は、すべての引数を消費するために、必要に応じて再利用されるのように2つの形式のプレースホルダを使用した。printf "%s%s"単純に、残りの引数連結のみ、出力の設定された第1のインスタンスでのセパレータを使用します。
AnyDev

3
@AndrDevEK:間違いを見つけてくれてありがとう。代わりに、私はのようなものを提案しますprintf "%s" "${foo[@]/#/$separator}"
musiphil

2
@musiphil、ありがとう。はい!次に、printfが冗長になり、その行をに減らすことができますIFS=; regex="${foo[*]/#/$separator}"。この時点で、これは本質的にgniourf_gniourfの答えになり、IMOは最初からよりきれいです。つまり、関数を使用してIFS変更と一時変数の範囲を制限します。
AnyDev 2014

145
$ foo=(a "b c" d)
$ bar=$(IFS=, ; echo "${foo[*]}")
$ echo "$bar"
a,b c,d

3
外側の二重引用符とコロンを囲む二重引用符は不要です。唯一の内側の二重引用符が必要です:bar=$( IFS=, ; echo "${foo[*]}" )
ceving

8
+1は、ループを必要とせず、外部コマンドを必要とせず、引数の文字セットに追加の制限を課さない最もコンパクトなソリューションです。
ceving

22
私はソリューションが好きですが、IFSが1文字の場合にのみ機能します
Jayen

8
@代わりにを使用すると*、これが機能しない理由はあり$(IFS=, ; echo "${foo[@]}")ますか?*が要素内の空白を既に保持していることがわかり@ます。これは通常、このために必要なためです。
haridsv 14

10
上記の自分の質問に対する答えを見つけました。答えは、IFSはに対してのみ認識されるということ*です。bashのmanページでは、次の「特殊パラメータ」と説明のための外観を検索*
haridsv

66

たぶん、例えば

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

echo "$FOOJOIN"

3
そうすると、IFS-が変数であると考えられます。実行する必要がありますecho "-${IFS}-"(波括弧は変数名からダッシュを区切ります)。
追って通知があるまで一時停止。

1
それでも(私はポイントを説明するためにダッシュを入れて...同じ結果を得たecho $IFSと同じことを行います。
デビッド・Wolever

41
そうは言っても、これはまだ機能しているようです…ですから、Bashでのほとんどのことのように、私はそれを理解して私の人生を続けるようにふりをします。
David Wolever、2009年

2
"-"は変数名に有効な文字ではないため、$ IFS-を使用するとシェルは正しいことを行います。$ {IFS}-は必要ありません(LinuxとSolarisではbash、ksh、sh、zsh)また同意します)。
イデリック2009年

2
@Davidエコーとデニスの違いは、彼が二重引用符を使用したことです。IFSの内容は、単語区切り文字の宣言として「入力時」に使用されるため、常に引用符なしの空の行が表示されます。
マーティンクレイトン

30

驚いたことに私の解決策はまだ与えられていません:)これは私にとって最も簡単な方法です。関数は必要ありません:

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

注:このソリューションは、非POSIXモードでうまく機能することが確認されています。でPOSIXモードでは、要素はまだ適切に参加されますが、IFS=,永続的になります。


残念ながら、1文字の区切り文字に対してのみ機能します
maoizm

24

これが、この仕事をする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}"
}

見て:

$ 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


$

これにより、末尾の改行も保持され、関数の結果を取得するためのサブシェルは必要ありません。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}"
}

1
あなたの最後の解決策は非常に良いですがjoin_ret、ローカル変数を作成し、最後にそれをエコーすることでよりクリーンにすることができます。これにより、join()を通常のシェルスクリプトで使用できるようになり$(join ":" one two three)ます。たとえば、グローバル変数は必要ありません。
James Sneeringer、2015年

1
@JamesSneeringerサブシェルを回避するために、この設計を意図的に使用しました。シェルスクリプトでは、他の多くの言語とは異なり、このように使用されるグローバル変数は必ずしも悪いことではありません。特に、サブシェルを回避するためにここにいる場合。さらに、$(...)末尾の改行を削除します。そのため、配列の最後のフィールドに末尾の改行が含まれている場合、これらは切り捨てられます(デザインで切り捨てられていないデモを参照してください)。
gniourf_gniourf 2015年

これは複数文字のセパレータで動作し、私を幸せにします^ _ ^
spiffytech 2015年

「なぜprintf -vが気に入らないのですか?」に対処するには:Bashでは、ローカル変数は実際には関数ローカルではないので、次のようにすることができます。(ローカル変数xで関数f1を呼び出し、次に関数f2を呼び出し、xを変更します-これはf1のスコープ内でローカルとして宣言されています)しかし、ローカル変数が実際に機能する方法はそうではありません。ローカル変数が実際にローカルである(または、たとえばbashとkshの両方で機能する必要があるスクリプト内にあると想定されている)場合、この「全体をこの名前の変数に格納して値を返す」方式で問題が発生します。
鉄人2016

15

これは既存のソリューションとそれほど違いはありませんが、別の関数を使用することを避けIFS、親シェルで変更せず、すべて1行で行います。

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

その結果

a,b,c

制限:区切り文字は1文字より長くすることはできません。


13

外部コマンドを使用しない:

$ 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

警告、それは要素に空白がないことを前提としています。


4
あなたは中間変数を使用したくない場合は、それも短く行うことができますecho ${FOO[@]} | tr ' ' ','
jesjimher

2
私は反対票を理解していません。これは、ここに掲載されている他のソリューションよりもはるかにコンパクトで読みやすいソリューションであり、スペースがあると機能しないことをはっきりと警告しています。
jesjimher 2016年

12

配列を文字列としてエコーし、スペースを改行に変換してから、次のように使用pasteしてすべてを1行に結合します。

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

結果:

a,b,c

これは私にとって最も速くてきれいなようです!


$FOOただし、配列の最初の要素にすぎません。また、これはスペースを含む配列要素では機能しません。
ベンジャミンW.

9

@doesnの再利用は問題ではありませんが、$ {:1}置換と中間変数の必要性を回避する1つのステートメントを使用します。

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

printfには、「引数を満たすために必要なだけ頻繁にフォーマット文字列が再利用されます。文字列の連結が文書化されるように、そのマニュアルページで。次に、トリックは、リストの長さを使用して最後のスペレータを切り刻むことです。カットは、フィールドの数としてLISTの長さのみを保持するためです。


7
s=$(IFS=, eval 'echo "${FOO[*]}"')

8
あなたはあなたの答えを具体化すべきです。
2013年

最高のもの。ありがとう!!
ピーターパンgz

4
セキュリティホールが開き、要素内のスペースが破壊されるため、この回答に反対票を投じることができればと思います。
eel ghEEz 2016

1
@bxmは確かに、スペースを保持しているようで、エコー引数コンテキストからのエスケープを許可していません。追加@Qすると、結合された値に結合子が含まれている場合に、結合された値が誤って解釈されないようにすることができると考えました。foo=("a ," "b ' ' c" "' 'd e" "f " ";" "ls -latr"); s=$(IFS=, eval 'echo "${foo[*]@Q}"'); echo "${s}"出力'a ,','b '\'' '\'' c',''\'' '\''d e','f ',';','ls -latr '
eel ghEEz

1
必要でない限り、サブシェルを使用するソリューションは避けてください。
konsolebox

5

任意の長さのセパレータを受け入れる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

これにより、先頭にコンマが付いた出力が生成されます。
Mark Renouf 2013

最後のbar = $ {bar:$ {#sep}}はセパレーターを削除します。私はコピーしてbashシェルに貼り付けるだけで機能します。どのシェルを使用していますか?
Riccardo Galli

2
任意のprintf 書式指定子。(例えば%s無意識で$sep問題が発生します。
Peter.O

sepで消毒できます${sep//\%/%%}${bar#${sep}}または${bar%${sep}}(代替)よりもあなたのソリューションが好きです。これは、結果を__ではなくのようなジェネリック変数に保存する関数に変換すると便利ですecho
konsolebox

function join_by { printf -v __ "${1//\%/%%}%s" "${@:2}"; __=${__:${#1}}; }
konsolebox

4
$ set a 'b c' d

$ history -p "$@" | paste -sd,
a,b c,d

これが一番上になるはずです。
Eric Walker、

6
これはトップであってはなりませんHISTSIZE=0
har-wradim 2015年

@ har-wradim、トリックはpaste -sd,歴史の使用についてではありません。
Veda

@ヴェーダいいえ、それは組み合わせの使用に関するものであり、それが機能しない場合はHISTSIZE=0-試してみてください。
har-wradim 2017

4

トップアンサーの短縮バージョン:

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

使用法:

joinStrings "$myDelimiter" "${myArray[@]}"

1
より長いバージョンですが、配列変数に引数のスライスのコピーを作成する必要はありません:join_strings () { local d="$1"; echo -n "$2"; shift 2 && printf '%s' "${@/#/$d}"; }
Rockallite

さらに別のバージョン: join_strings () { local d="$1"; echo -n "$2"; shift 2 && printf '$d%s' "${@}"; } これは使用法で機能します:join_strings 'delim' "${array[@]}"または引用符で囲まれていない:join_strings 'delim' ${array[@]}
Cometsong

4

これまでのすべての世界のベストを次のアイデアと組み合わせます。

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

この小さな傑作は

  • 100%純粋なbash(IFSを使用したパラメーター拡張は一時的に設定解除され、外部呼び出しなし、printfなし...)
  • コンパクトで完全、完璧(単一文字および複数文字のリミッターで動作し、空白、改行、その他のシェル特殊文字を含むリミッターで動作し、空の区切り文字で動作します)
  • 効率的(サブシェルなし、配列コピーなし)
  • シンプルで愚かで、ある程度、美しく、有益な

例:

$ 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

1
それほど良くない:少なくとも2つの問題:1. join_ws ,(引数なしで)誤って出力する,,。2. join_ws , -e誤って何も出力しません(これは、のecho代わりに誤って使用しているためですprintf)。あなたが使用宣伝なぜ私は実際には知らないechoの代わりにprintfecho悪名高い壊れた、とされるprintf堅牢な組み込みです。
gniourf_gniourf 2018年

1

今私は使っています:

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 ' ' ','`"

これは機能しますが、(一般的な場合)配列要素にスペースがあると、ひどく壊れてしまいます。

(興味のある方は、これはpep8.pyのラッパースクリプトです


これらの配列値はどこから取得しますか?そのようにハードコーディングしているなら、なぜfoo = "a、b、c"。?
ghostdog74

この場合、実際に値をハードコーディングしていますが、値を配列に入れて、それぞれにコメントできるようにしたいと考えています。答えを更新して、私が何を意味するかをお見せします。
David Wolever、2009年

実際にbashを使用していると仮定すると、これはより適切に機能する可能性がありますARGS="--ignore $(echo "${TO_IGNORE[@]}" | tr ' ' ',')"。演算子$()はbackticsよりも強力です($()andのネストを許可します"")。${TO_IGNORE[@]}二重引用符で囲むことも役立つはずです。
kevinarpe 2013年

1

私の試み。

$ array=(one two "three four" five)
$ echo "${array[0]}$(printf " SEP %s" "${array[@]:1}")"
one SEP two SEP three four SEP five

1

複数文字のセパレーターにはperlを使用します。

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

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

または1行で:

perl -le 'print join(shift, @ARGV);' ', ' 1 2 3
1, 2, 3

けれども私のために働き、join上のいくつかのがらくたと名前が競合OS X..私はそれを呼びたいconjoined、または多分jackie_joyner_kersee
Alex Grey

1

これまでの最高の世界の組み合わせに関する詳細なコメントを@gniourf_gniourfに感謝します。十分に設計およびテストされていないコードを投稿して申し訳ありません。ここでより良い試みです。

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

概念によるこの美しさは

  • (まだ)100%純粋なbash(printfも組み込みであることを明示的に指摘してくれてありがとう。これまではこれに気づきませんでした...)
  • 複数文字の区切り文字で動作します
  • よりコンパクトでより完全になりました。今回は、シェルスクリプトからのランダムなサブストリングを使用して、シェルの特殊文字または制御文字の使用、またはセパレーターとパラメーターの両方での文字なしの使用、およびエッジケースについて、慎重に検討し、長期的なストレステストを行いました。 、コーナーケースやその他の問題点など、まったく議論はありません。これはバグがなくなることを保証するものではありませんが、バグを見つけるのは少し難しくなります。ところで、現在トップの投票された回答や関連するものでさえ、そのようなものに悩まされています-eバグ...

追加の例:

$ 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 $ 
$

1

結合したい要素がスペースで区切られた文字列だけの配列ではない場合、次のようなことができます:

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

たとえば、私の使用例では、いくつかの文字列がシェルスクリプトで渡され、SQLクエリで実行するためにこれを使用する必要があります。

./my_script "aa bb cc dd"

my_scriptでは、 "SELECT * FROM table WHERE name IN( 'aa'、 'bb'、 'cc'、 'dd')を実行する必要があります。その場合、上記のコマンドが役立ちます。


printf -v bar ...サブシェルでprintfループを実行して出力をキャプチャする代わりにを使用できます。
codeforester 2018年

上記の派手な賛成の解決策はすべて機能しませんでしたが、あなたの粗雑な解決策は私のために機能しました(Y)
ishandutta2007 '26

1

以下は、ほとんどの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[@]}"
}

すばらしいBashコードですが、POSIXに配列(またはlocalがまったくありません
Anders Kaseorg、

@Anders:うん、私は非常に最近、これに苦労して学んだ:(ほとんどのPOSIX互換のシェルが配列をサポートするように見えるんので、私は今かかわらのためにそれを残しておきます。
user541686

1

変数の間接参照を使用して配列を直接参照することもできます。名前付き参照も使用できますが、4.3でのみ使用可能になりました。

この形式の関数を使用する利点は、区切り文字をオプションにすることができることです(デフォルトはデフォルトの最初の文字になります)。 IFSあるスペースです。て空の文字列にすることもできます)、値を2度展開することを回避できます(最初にパラメータとして渡されたとき、および"$@"関数内として渡されたとき)。

このソリューションでは、ユーザーがコマンド置換内で関数を呼び出す必要もありません。サブシェルを呼び出して、別の変数に割り当てられた文字列の結合バージョンを取得します。

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.

関数には、よりわかりやすい名前を自由に使用してください。

これは3.1から5.0-alphaまで機能します。観察されたように、変数の間接化は変数だけでなく他のパラメーターでも機能します。

パラメータは、値を格納するエンティティです。名前、番号、または以下の「特殊パラメーター」にリストされている特殊文字のいずれかになります。変数は、名前で示されるパラメーターです。

配列と配列要素もパラメータ(値を格納するエンティティ)であり、配列への参照は技術的にはパラメータへの参照でもあります。そして特別なパラメータ@と同様に、array[@]同様に、有効な参照も作成します。

パラメーター自体からの参照を逸脱する変更または選択された形式の拡張(サブストリング拡張など)は機能しなくなりました。

更新

Bash 5.0のリリースバージョンでは、変数の間接参照はすでに間接展開と呼ばれ、その動作はマニュアルに明示的に文書化されています。

パラメーターの最初の文字が感嘆符(!)であり、パラメーターが名前参照でない場合は、間接参照のレベルが導入されます。Bashは、残りのパラメーターを展開することによって形成された値を新しいパラメーターとして使用します。次に、これが拡張され、その値が、元のパラメーターの拡張ではなく、残りの拡張で使用されます。これは間接展開と呼ばれます。

のドキュメントでは${parameter}parameter「(パラメータ)または配列参照で説明されているシェルパラメータ」と呼ばれていることに注意してください。また、配列のドキュメントでは、「配列の任意の要素は、を使用して参照される可能性が${name[subscript]}あると記載されています。 これは__r[@]、配列参照が作成されます。

引数バージョンで結合

Riccardo Galliの回答で私のコメントを参照してください。


2
__変数名として使用する特定の理由はありますか?コードを本当に読めなくします。
PesaThe 2018

@PesaTheそれは単なる好みです。私は、戻り変数に総称名を使用することを好みます。他の非総称名は、特定の機能に起因するものであり、記憶する必要があります。さまざまな変数の値を返す複数の関数を呼び出すと、コードがわかりにくくなる可能性があります。総称名を使用すると、スクリプト作成者は値を戻り変数から適切な変数に転送して競合を回避し、戻り値の場所が明示的になるため、コードが読みやすくなります。ただし、私はそのルールにいくつかの例外を設けています。
konsolebox 2018

0

このアプローチは、値内のスペースを処理しますが、ループが必要です。

#!/bin/bash

FOO=( a b c )
BAR=""

for index in ${!FOO[*]}
do
    BAR="$BAR,${FOO[$index]}"
done
echo ${BAR:1}

0

配列をループで作成する場合、簡単な方法を次に示します。

arr=()
for x in $(some_cmd); do
   arr+=($x,)
done
arr[-1]=${arr[-1]%,}
echo ${arr[*]}

0

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

これが最も簡単な方法です。

例、

arr=(1 2 3 4 5)
x=${"${arr[*]}"// /,}
echo $x  # output: 1,2,3,4,5

1
これは、スペースのある文字列では正しく機能しません。`t=(a "b c" d); echo $ {t [2]}(「b c」を出力します); echo $ {"$ {t [*]}" // /、}(印刷物a、b、c、d)
kounoupis

7
bash: ${"${arr[*]}"// /,}: bad substitution
キャメロンハドソン

0

おそらくパーティーに遅れますが、これは私にとってはうまくいきます:

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

  echo "${output}"
}

-1

たぶん私はbash / zsh全体の初心者なので、明らかなものがないかもしれませんがprintf、まったく使用する必要がないように見えます。それなしでやるのが本当に醜いこともない。

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

少なくとも、これまでのところ問題なく機能しています。

たとえば、join \| *.sh私は自分の~ディレクトリにいるとしましょうutilities.sh|play.sh|foobar.sh。私には十分です。

編集:これは基本的にはNil Geisweillerの答えですが、関数に一般化されています。


1
私は賛成派ではありませんが、関数内でグローバルを操作するのはかなり奇妙に見えます。
tripleee

-2
liststr=""
for item in list
do
    liststr=$item,$liststr
done
LEN=`expr length $liststr`
LEN=`expr $LEN - 1`
liststr=${liststr:0:$LEN}

これにより、最後の余分なコンマも処理されます。私はbashのエキスパートではありません。これはより初歩的で理解しやすいので、ちょうど私の2c


-2
awk -v sep=. 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' "${arr[@]}"

または

$ a=(1 "a b" 3)
$ b=$(IFS=, ; echo "${a[*]}")
$ echo $b
1,a b,3
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.