web-dev-qa-db-ja.com

グローバルを使用せずにbashで配列を返す方法は?

配列を作成する関数があり、配列を呼び出し元に返したい:

create_array() {
  local my_list=("a", "b", "c")
  echo "${my_list[@]}"
}

my_algorithm() {
  local result=$(create_array)
}

これにより、拡張文字列のみが取得されます。グローバルを使用せずにmy_listを「返す」にはどうすればよいですか?

67
helpermethod

グローバルの何が問題になっていますか?

配列を返すことは実際には実用的ではありません。落とし穴はたくさんあります。

そうは言っても、変数に同じ名前を付けても問題ない場合に機能する1つの手法を次に示します。

$ f () { local a; a=(abc 'def ghi' jkl); declare -p a; }
$ g () { local a; eval $(f); declare -p a; }
$ f; declare -p a; echo; g; declare -p a
declare -a a='([0]="abc" [1]="def ghi" [2]="jkl")'
-bash: declare: a: not found

declare -a a='([0]="abc" [1]="def ghi" [2]="jkl")'
-bash: declare: a: not found

declare -pコマンド(f()のコマンドを除く)は、デモの目的で配列の状態を表示するために使用されます。f()では、配列を返すメカニズムとして使用されます。

配列に別の名前を付ける必要がある場合、次のようなことができます。

$ g () { local b r; r=$(f); r="declare -a b=${r#*=}"; eval "$r"; declare -p a; declare -p b; }
$ f; declare -p a; echo; g; declare -p a
declare -a a='([0]="abc" [1]="def ghi" [2]="jkl")'
-bash: declare: a: not found

-bash: declare: a: not found
declare -a b='([0]="abc" [1]="def ghi" [2]="jkl")'
-bash: declare: a: not found
34

Bashバージョン4.3以降では、 nameref を使用して、呼び出し元が配列名を渡し、呼び出し先が名前付き配列を使用して名前付き配列間接的に

#!/usr/bin/env bash

create_array() {
    local -n arr=$1              # use nameref for indirection
    arr=(one "two three" four)
}

use_array() {
    local my_array
    create_array my_array       # call function to populate the array
    echo "inside use_array"
    declare -p my_array         # test the array
}

use_array                       # call the main function

出力を生成します。

inside use_array
declare -a my_array=([0]="one" [1]="two three" [2]="four")

関数で既存の配列を更新することもできます。

update_array() {
    local -n arr=$1              # use nameref for indirection
    arr+=("two three" four)      # update the array
}

use_array() {
    local my_array=(one)
    update_array my_array       # call function to update the array
}

コマンド置換$()は呼び出されている関数の標準出力を取得する必要がないため、これはよりエレガントで効率的なアプローチです。 。また、関数が複数の出力を返す場合にも役立ちます。出力の数と同じ数の名前参照を単純に使用できます。


Bash Manual がnamerefについて述べていることは次のとおりです。

変数にnameref属性を割り当てるには、declareまたはlocal組み込みコマンド(Bash Builtinsを参照)の-nオプションを使用して、namerefまたは別の変数への参照を作成します。これにより、変数を間接的に操作できます。 nameref変数の参照、割り当て、設定解除、または属性の変更(nameref属性自体の使用または変更以外)が行われるたびに、実際には、nameref変数の値で指定された変数に対して操作が実行されます。 namerefは一般的にシェル関数内で使用され、関数に引数として渡される名前の変数を参照します。たとえば、変数名が最初の引数としてシェル関数に渡された場合、次を実行します

関数内のdeclare -n ref = $ 1は、値が最初の引数として渡された変数名であるnameref変数refを作成します。 refへの参照と割り当て、およびその属性の変更は、名前が$ 1として渡された変数への参照、割り当て、および属性の変更として扱われます。

22
codeforester

Bashはデータ構造を戻り値として渡すことはできません。戻り値は、0〜255の終了ステータスである必要があります。ただし、必要に応じて、コマンドまたはプロセス置換を使用して、コマンドをevalステートメントに渡すことができます。

これはめったにトラブルの価値はありません、私見。 Bashでデータ構造を渡す必要がある場合は、グローバル変数を使用します-それが目的です。ただし、何らかの理由でこれを行いたくない場合は、位置パラメータの観点から考えてください。

例は、グローバル変数の代わりに位置パラメータを使用するように簡単に書き直すことができます。

use_array () {
    for idx in "$@"; do
        echo "$idx"
    done
}

create_array () {
    local array=("a" "b" "c")
    use_array "${array[@]}"
}

ただし、これにより、ある程度の不必要な複雑さが生じます。通常、bash関数は、副作用のあるプロシージャのように処理し、順番に呼び出すと最も効果的に機能します。

# Gather values and store them in FOO.
get_values_for_array () { :; }

# Do something with the values in FOO.
process_global_array_variable () { :; }

# Call your functions.
get_values_for_array
process_global_array_variable

心配しているのがグローバル名前空間を汚染している場合、 nset builtin を使用して、完了後にグローバル変数を削除することもできます。元の例を使用して、my_listを(localキーワードを削除して)グローバルにし、unset my_listmy_algorithmの末尾に移動して、自分の後をクリーンアップします。

15
Todd A. Jacobs

Matt McClureが開発した手法を使用します。 http://notes-matthewlmcclure.blogspot.com/2009/12/return-array-from-bash-function-v-2.html

グローバル変数を回避することは、パイプ内で関数を使用できることを意味します。以下に例を示します。

#!/bin/bash

makeJunk()
{
   echo 'this is junk'
   echo '#more junk and "b@d" characters!'
   echo '!#$^%^&(*)_^&% ^$#@:"<>?/.,\\"'"'"
}

processJunk()
{
    local -a arr=()    
    # read each input and add it to arr
    while read -r line
    do 
       arr[${#arr[@]}]='"'"$line"'" is junk'; 
    done;

    # output the array as a string in the "declare" representation
    declare -p arr | sed -e 's/^declare -a [^=]*=//'
}

# processJunk returns the array in a flattened string ready for "declare"
# Note that because of the pipe processJunk cannot return anything using
# a global variable
returned_string=`makeJunk | processJunk`

# convert the returned string to an array named returned_array
# declare correctly manages spaces and bad characters
eval "declare -a returned_array=${returned_string}"

for junk in "${returned_array[@]}"
do
   echo "$junk"
done

出力は次のとおりです。

"this is junk" is junk
"#more junk and "b@d" characters!" is junk
"!#$^%^&(*)_^&% ^$#@:"<>?/.,\\"'" is junk
10
Steve Zobell

元のソリューションではそれほど遠くありませんでした。いくつかの問題があり、カンマを区切り記号として使用し、返されたアイテムをリストにキャプチャできませんでした。これを試してください:

my_algorithm() {
  local result=( $(create_array) )
}

create_array() {
  local my_list=("a" "b" "c")  
  echo "${my_list[@]}" 
}

埋め込みスペースに関するコメントを考慮すると、IFSを使用したいくつかの微調整で解決できます。

my_algorithm() {
  oldIFS="$IFS"
  IFS=','
  local result=( $(create_array) )
  IFS="$oldIFS"
  echo "Should be 'c d': ${result[1]}"
}

create_array() {
  IFS=','
  local my_list=("a b" "c d" "e f") 
  echo "${my_list[*]}" 
}
9
cdarke

'declare -p'ビルトインに基づく純粋なbash、最小限の堅牢なソリューション—異常なグローバル変数なし

このアプローチには、次の3つのステップが含まれます。

  1. 'declare -p'を使用して配列を変換し、出力を変数に保存します。
    myVar="$( declare -p myArray )"
    _declare -p_ステートメントの出力を使用して、配列を再作成できます。たとえば、_declare -p myVar_の出力は次のようになります。
    declare -a myVar='([0]="1st field" [1]="2nd field" [2]="3rd field")'
  2. Echoビルトインを使用して、変数を関数に渡すか、そこから変数を返します。
    • 変数をエコーするときに配列フィールドのウィットスペースを保持するために、IFSは一時的に制御文字(垂直タブなど)に設定されます。
    • 変数内の宣言ステートメントの右側のみがエコーされます-これは、$ {parameter#Word}の形式のパラメーター展開によって実現できます。上記の例に関して:_${myVar#*=}_
  3. 最後に、evalおよび 'declare -a'ビルトインを使用して渡される配列を再作成します。

例1-関数から配列を返す

_#!/bin/bash

# Example 1 - return an array from a function

function my-fun () {
 # set up a new array with 3 fields - note the whitespaces in the
 # 2nd (2 spaces) and 3rd (2 tabs) field
 local myFunArray=( "1st field" "2nd  field" "3rd       field" )

 # show its contents on stderr (must not be output to stdout!)
 echo "now in $FUNCNAME () - showing contents of myFunArray" >&2
 echo "by the help of the 'declare -p' builtin:" >&2
 declare -p myFunArray >&2

 # return the array
 local myVar="$( declare -p myFunArray )"
 local IFS=$'\v';
 echo "${myVar#*=}"

 # if the function would continue at this point, then IFS should be
 # restored to its default value: <space><tab><newline>
 IFS=' '$'\t'$'\n';
}

# main

# call the function and recreate the array that was originally
# set up in the function
eval declare -a myMainArray="$( my-fun )"

# show the array contents
echo ""
echo "now in main part of the script - showing contents of myMainArray"
echo "by the help of the 'declare -p' builtin:"
declare -p myMainArray

# end-of-file
_

例1の出力:

_now in my-fun () - showing contents of myFunArray
by the help of the 'declare -p' builtin:
declare -a myFunArray='([0]="1st field" [1]="2nd  field" [2]="3rd       field")'

now in main part of the script - showing contents of myMainArray
by the help of the 'declare -p' builtin:
declare -a myMainArray='([0]="1st field" [1]="2nd  field" [2]="3rd      field")'
_

例2-配列を関数に渡す

_#!/bin/bash

# Example 2 - pass an array to a function

function my-fun () {
 # recreate the array that was originally set up in the main part of
 # the script
 eval declare -a myFunArray="$( echo "$1" )"

 # note that myFunArray is local - from the bash(1) man page: when used
 # in a function, declare makes each name local, as with the local
 # command, unless the ‘-g’ option is used.

 # IFS has been changed in the main part of this script - now that we
 # have recreated the array it's better to restore it to the its (local)
 # default value: <space><tab><newline>
 local IFS=' '$'\t'$'\n';

 # show contents of the array
 echo ""
 echo "now in $FUNCNAME () - showing contents of myFunArray"
 echo "by the help of the 'declare -p' builtin:"
 declare -p myFunArray
}

# main

# set up a new array with 3 fields - note the whitespaces in the
# 2nd (2 spaces) and 3rd (2 tabs) field
myMainArray=( "1st field" "2nd  field" "3rd     field" )

# show the array contents
echo "now in the main part of the script - showing contents of myMainArray"
echo "by the help of the 'declare -p' builtin:"
declare -p myMainArray

# call the function and pass the array to it
myVar="$( declare -p myMainArray )"
IFS=$'\v';
my-fun $( echo "${myVar#*=}" )

# if the script would continue at this point, then IFS should be restored
# to its default value: <space><tab><newline>
IFS=' '$'\t'$'\n';

# end-of-file
_

例2の出力:

_now in the main part of the script - showing contents of myMainArray
by the help of the 'declare -p' builtin:
declare -a myMainArray='([0]="1st field" [1]="2nd  field" [2]="3rd      field")'

now in my-fun () - showing contents of myFunArray
by the help of the 'declare -p' builtin:
declare -a myFunArray='([0]="1st field" [1]="2nd  field" [2]="3rd       field")'
_
8
F.M.

便利な例:関数から配列を返す

function Query() {
  local _tmp=`echo -n "$*" | mysql 2>> zz.err`;
  echo -e "$_tmp";
}

function StrToArray() {
  IFS=$'\t'; set $1; for item; do echo $item; done; IFS=$oIFS;
}

sql="SELECT codi, bloc, requisit FROM requisits ORDER BY codi";
qry=$(Query $sql0);
IFS=$'\n';
for row in $qry; do
  r=( $(StrToArray $row) );
  echo ${r[0]} - ${r[1]} - ${r[2]};
done
4
Rafael

[注:この答え for 私にとって意味のない理由)の編集として以下が拒否されました (編集はnotであるため、投稿の著者に対応することを意図していました!)、私はそれを別のものにする提案を取っています回答。]

Steve ZobellによるMatt McClureの手法の適応 のより単純な実装では、bashビルトインを使用します( version == 4readarray提案どおり) RastaMatt により、実行時に配列に変換できる配列の表現を作成します。 (readarraymapfileの両方が同じコードに名前を付けていることに注意してください。)グローバルを回避し(パイプで関数を使用できるようにする)、厄介な文字を処理します。

より完全に開発された(たとえば、よりモジュール化された)が、まだちょっとおもちゃの例については、 bash_pass_arrays_between_functions を参照してください。以下に、簡単に実行可能ないくつかの例を示します。外部リンクに関するモデレーターのb!tchingを回避するためにここに記載されています。

次のブロックを切り取り、bashターミナルに貼り付けて/tmp/source.shおよび/tmp/junk1.shを作成します。

FP='/tmp/source.sh'     # path to file to be created for `source`ing
cat << 'EOF' > "${FP}"  # suppress interpretation of variables in heredoc
function make_junk {
   echo 'this is junk'
   echo '#more junk and "b@d" characters!'
   echo '!#$^%^&(*)_^&% ^$#@:"<>?/.,\\"'"'"
}

### Use 'readarray' (aka 'mapfile', bash built-in) to read lines into an array.
### Handles blank lines, whitespace and even nastier characters.
function lines_to_array_representation {
    local -a arr=()
    readarray -t arr
    # output array as string using 'declare's representation (minus header)
    declare -p arr | sed -e 's/^declare -a [^=]*=//'
}
EOF

FP1='/tmp/junk1.sh'      # path to script to run
cat << 'EOF' > "${FP1}"  # suppress interpretation of variables in heredoc
#!/usr/bin/env bash

source '/tmp/source.sh'  # to reuse its functions

returned_string="$(make_junk | lines_to_array_representation)"
eval "declare -a returned_array=${returned_string}"
for elem in "${returned_array[@]}" ; do
    echo "${elem}"
done
EOF
chmod u+x "${FP1}"
# newline here ... just hit Enter ...

/tmp/junk1.shを実行します:出力は

this is junk
#more junk and "b@d" characters!
!#$^%^&(*)_^&% ^$#@:"<>?/.,\\"'

lines_to_array_representationは空白行も処理します。次のブロックをbashターミナルに貼り付けてみてください。

FP2='/tmp/junk2.sh'      # path to script to run
cat << 'EOF' > "${FP2}"  # suppress interpretation of variables in heredoc
#!/usr/bin/env bash

source '/tmp/source.sh'  # to reuse its functions

echo '`bash --version` the normal way:'
echo '--------------------------------'
bash --version
echo # newline

echo '`bash --version` via `lines_to_array_representation`:'
echo '-----------------------------------------------------'
bash_version="$(bash --version | lines_to_array_representation)"
eval "declare -a returned_array=${bash_version}"
for elem in "${returned_array[@]}" ; do
    echo "${elem}"
done
echo # newline

echo 'But are they *really* the same? Ask `diff`:'
echo '-------------------------------------------'

echo 'You already know how to capture normal output (from `bash --version`):'
declare -r PATH_TO_NORMAL_OUTPUT="$(mktemp)"
bash --version > "${PATH_TO_NORMAL_OUTPUT}"
echo "normal output captured to file @ ${PATH_TO_NORMAL_OUTPUT}"
ls -al "${PATH_TO_NORMAL_OUTPUT}"
echo # newline

echo 'Capturing L2AR takes a bit more work, but is not onerous.'
echo "Look @ contents of the file you're about to run to see how it's done."

declare -r RAW_L2AR_OUTPUT="$(bash --version | lines_to_array_representation)"
declare -r PATH_TO_COOKED_L2AR_OUTPUT="$(mktemp)"
eval "declare -a returned_array=${RAW_L2AR_OUTPUT}"
for elem in "${returned_array[@]}" ; do
    echo "${elem}" >> "${PATH_TO_COOKED_L2AR_OUTPUT}"
done
echo "output from lines_to_array_representation captured to file @ ${PATH_TO_COOKED_L2AR_OUTPUT}"
ls -al "${PATH_TO_COOKED_L2AR_OUTPUT}"
echo # newline

echo 'So are they really the same? Per'
echo "\`diff -uwB "${PATH_TO_NORMAL_OUTPUT}" "${PATH_TO_COOKED_L2AR_OUTPUT}" | wc -l\`"
diff -uwB "${PATH_TO_NORMAL_OUTPUT}" "${PATH_TO_COOKED_L2AR_OUTPUT}" | wc -l
echo '... they are the same!'
EOF
chmod u+x "${FP2}"
# newline here ... just hit Enter ...

/tmp/junk2.sh @コマンドラインを実行します。出力は私のものに似ているはずです:

`bash --version` the normal way:
--------------------------------
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

`bash --version` via `lines_to_array_representation`:
-----------------------------------------------------
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

But are they *really* the same? Ask `diff`:
-------------------------------------------
You already know how to capture normal output (from `bash --version`):
normal output captured to file @ /tmp/tmp.Ni1bgyPPEw
-rw------- 1 me me 308 Jun 18 16:27 /tmp/tmp.Ni1bgyPPEw

Capturing L2AR takes a bit more work, but is not onerous.
Look @ contents of the file you're about to run to see how it's done.
output from lines_to_array_representation captured to file @ /tmp/tmp.1D6O2vckGz
-rw------- 1 me me 308 Jun 18 16:27 /tmp/tmp.1D6O2vckGz

So are they really the same? Per
`diff -uwB /tmp/tmp.Ni1bgyPPEw /tmp/tmp.1D6O2vckGz | wc -l`
0
... they are the same!
3
TomRoche

外部配列参照およびIFS操作のないソリューションを次に示します。

# add one level of single quotes to args, eval to remove
squote () {
    local a=("$@")
    a=("${a[@]//\'/\'\\\'\'}")   # "'" => "'\''"
    a=("${a[@]/#/\'}")           # add "'" prefix to each Word
    a=("${a[@]/%/\'}")           # add "'" suffix to each Word
    echo "${a[@]}"
}

create_array () {
    local my_list=(a "b 'c'" "\\\"d
")
    squote "${my_list[@]}"
}

my_algorithm () {
    eval "local result=($(create_array))"
    # result=([0]="a" [1]="b 'c'" [2]=$'\\"d\n')
}
2
Matei David

私は最近、関数が呼び出しスタックの上位の関数で宣言された変数に直接アクセスできるという点で、BASHの奇妙な点を発見しました。この機能を活用する方法を考え始めたばかりですが(利点と危険の両方を約束します)、1つの明らかなアプリケーションはこの問題の精神に対する解決策です。

また、配列の作成を委任するときにグローバル変数を使用するのではなく、戻り値を取得することをお勧めします。私の好みにはいくつかの理由がありますが、その中には、既存の値を乱す可能性を避けるためと、後でアクセスしたときに無効になる可能性のある値を残さないためです。これらの問題には回避策がありますが、最も簡単なのは、コードが終了したときに変数をスコープ外にすることです。

私のソリューションでは、必要なときに配列が使用可能になり、関数が戻ったときに破棄され、同じ名前のグローバル変数をそのまま残します。

#!/bin/bash

myarr=(global array elements)

get_an_array()
{
   myarr=( $( date +"%Y %m %d" ) )
}

request_array()
{
   declare -a myarr
   get_an_array "myarr"
   echo "New contents of local variable myarr:"
   printf "%s\n" "${myarr[@]}"
}

echo "Original contents of global variable myarr:"
printf "%s\n" "${myarr[@]}"
echo

request_array 

echo
echo "Confirm the global myarr was not touched:"
printf "%s\n" "${myarr[@]}"

このコードの出力は次のとおりです。 program output

関数request_arrayget_an_arrayを呼び出すとき、get_an_arraymyarrrequest_arrayに対してローカルな変数。 myarrdeclareで作成されるため、request_arrayに対してローカルであり、したがってrequest_arrayが戻ります。

このソリューションは文字通り値を返しませんが、全体として考えると、真の関数の戻り値の約束を満たしていることをお勧めします。

2
chuckj

さまざまな実装を試みましたが、スペースを含む要素を持つ配列は保存されませんでした...すべてがechoを使用しなければならなかったからです。

# These implementations only work if no array items contain spaces.
use_array() {  eval echo  '(' \"\${${1}\[\@\]}\" ')';  }
use_array() {  local _array="${1}[@]"; echo '(' "${!_array}" ')';  }

解決

それから私は デニスウィリアムソンの答え に出会いました。私は彼の方法を以下の関数に組み込んで、a)任意の配列を受け入れ、b)配列の受け渡し、複製、および追加に使用できるようにしました。

# Print array definition to use with assignments, for loops, etc.
#   varname: the name of an array variable.
use_array() {
    local r=$( declare -p $1 )
    r=${r#declare\ -a\ *=}
    # Strip keys so printed definition will be a simple list (like when using
    # "${array[@]}").  One side effect of having keys in the definition is 
    # that when appending arrays (i.e. `a1+=$( use_array a2 )`), values at
    # matching indices merge instead of pushing all items onto array.
    echo ${r//\[[0-9]\]=}
}
# Same as use_array() but preserves keys.
use_array_assoc() {
    local r=$( declare -p $1 )
    echo ${r#declare\ -a\ *=}
}  

その後、他の関数は、キャッチ可能な出力または間接引数を使用して配列を返すことができます。

# catchable output
return_array_by_printing() {
    local returnme=( "one" "two" "two and a half" )
    use_array returnme
}
eval test1=$( return_array_by_printing )

# indirect argument
return_array_to_referenced_variable() {
    local returnme=( "one" "two" "two and a half" )
    eval $1=$( use_array returnme )
}
return_array_to_referenced_variable test2

# Now both test1 and test2 are arrays with three elements
2

最近、同様の機能が必要になったため、以下は RashaMattSteve Zobell による提案を組み合わせたものです。

  1. echo各配列/リスト要素を関数内から個別の行として
  2. mapfileを使用して、関数によってエコーされるすべての配列/リスト要素を読み取ります。

私が見る限り、文字列はそのまま保持され、空白は保持されます。

#!bin/bash

function create-array() {
  local somearray=("aaa" "bbb ccc" "d" "e f g h")
  for elem in "${somearray[@]}"
  do
    echo "${elem}"
  done
}

mapfile -t resa <<< "$(create-array)"

# quick output check
declare -p resa

いくつかのバリエーション…

#!/bin/bash

function create-array-from-ls() {
  local somearray=("$(ls -1)")
  for elem in "${somearray[@]}"
  do
    echo "${elem}"
  done
}

function create-array-from-args() {
  local somearray=("$@")
  for elem in "${somearray[@]}"
  do
    echo "${elem}"
  done
}


mapfile -t resb <<< "$(create-array-from-ls)"
mapfile -t resc <<< "$(create-array-from-args 'xxx' 'yy zz' 't s u' )"

sentenceA="create array from this sentence"
sentenceB="keep this sentence"

mapfile -t resd <<< "$(create-array-from-args ${sentenceA} )"
mapfile -t rese <<< "$(create-array-from-args "$sentenceB" )"
mapfile -t resf <<< "$(create-array-from-args "$sentenceB" "and" "this words" )"

# quick output check
declare -p resb
declare -p resc
declare -p resd
declare -p rese
declare -p resf
2
compota

これは、単に配列変数を関数に渡し、この変数に配列値を割り当ててから、関数の外部でこの変数を使用することでも実行できます。例えば。

create_array() {
  local  __resultArgArray=$1
  local my_list=("a" "b" "c")
  eval $__resultArgArray="("${my_list[@]}")"
}

my_algorithm() {
  create_array result
  echo "Total elements in the array: ${#result[@]}"
  for i in "${result[@]}"
  do
    echo $i
  done
}

my_algorithm
1
MNA

ソースデータが各リスト要素で別々の行にフォーマットされている場合、mapfileビルトインはリストを配列に読み込む簡単でエレガントな方法です。

$ list=$(ls -1 /usr/local)           # one item per line

$ mapfile -t arrayVar <<<"$list"     # -t trims trailing newlines

$ declare -p arrayVar | sed 's#\[#\n[#g'
declare -a arrayVar='(
[0]="bin"
[1]="etc"
[2]="games"
[3]="include"
[4]="lib"
[5]="man"
[6]="sbin"
[7]="share"
[8]="src")'

readビルトインと同様に、割り当てられた配列変数は後続のステートメントで使用できないため(* bashジョブ制御が無効にされていない限り)、通常*パイプライン(またはサブシェル)でmapfileを使用しませんおよびshopt -s lastpipeが設定されます)。

$ help mapfile
mapfile: mapfile [-n count] [-O Origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
    Read lines from the standard input into an indexed array variable.

    Read lines from the standard input into the indexed array variable ARRAY, or
    from file descriptor FD if the -u option is supplied.  The variable MAPFILE
    is the default ARRAY.

    Options:
      -n count  Copy at most COUNT lines.  If COUNT is 0, all lines are copied.
      -O Origin Begin assigning to ARRAY at index Origin.  The default index is 0.
      -s count  Discard the first COUNT lines read.
      -t                Remove a trailing newline from each line read.
      -u fd             Read lines from file descriptor FD instead of the standard input.
      -C callback       Evaluate CALLBACK each time QUANTUM lines are read.
      -c quantum        Specify the number of lines read between each call to CALLBACK.

    Arguments:
      ARRAY             Array variable name to use for file data.

    If -C is supplied without -c, the default quantum is 5000.  When
    CALLBACK is evaluated, it is supplied the index of the next array
    element to be assigned and the line to be assigned to that element
    as additional arguments.

    If not supplied with an explicit Origin, mapfile will clear ARRAY before
    assigning to it.

    Exit Status:
    Returns success unless an invalid option is given or ARRAY is readonly or
    not an indexed array.
0
RashaMatt