ファイルからBash配列に行を読み取ります

2012年07月09日に質問されました。  ·  閲覧回数 443k回  ·  ソース

Homunculus Reticulli picture
2012年07月09日

行を含むファイルをBash配列に読み込もうとしています。

私はこれまでに次のことを試しました。

試行1

a=( $( cat /path/to/filename ) )

試行2

index=0
while read line ; do
    MYARRAY[$index]="$line"
    index=$(($index+1))
done < /path/to/filename

どちらの試行も、ファイルの最初の行を含む1つの要素配列のみを返します。 私は何が間違っているのですか?

私はbash4.1.5を実行しています

回答

chepner picture
2012年07月09日
290

readarrayコマンド(スペルもmapfile )はbash4.0で導入されました。

readarray -t a < /path/to/filename
nhed picture
2012年07月09日
129

BinaryZebraのコメントからここcommand eval追加すると、式を現在の実行環境に保持できますが、前の式は評価期間中のみ保持されます。

スペースやタブがなく、改行/ CRだけの$ IFSを使用します

$ IFS=$'\r\n' GLOBIGNORE='*' command eval  'XYZ=($(cat /etc/passwd))'
$ echo "${XYZ[5]}"
sync:x:5:0:sync:/sbin:/bin/sync

また、配列を適切に設定しているが、読み方が間違っている可能性があることにも注意してください。上記の例のように、二重引用符""と中括弧{}両方を使用してください。


編集:

グロブ拡張の可能性についてのコメント、特にのgniourf-gniourfのコメントで、私の回答に関する多くの警告に注意してください。

これらすべての警告を念頭に置いて、私はまだこの答えをここに残しています(はい、bash 4は何年も前から出ていますが、2/3年しか経っていない一部のMacがデフォルトのシェルとしてpre-4を持っていることを思い出します)

その他の注意事項:

以下のdrizztの提案に従い、フォークされたサブシェル+猫を次のように置き換えることもできます

$(</etc/passwd)

私が時々使用する他のオプションは、IFSをXIFSに設定し、後で復元することです。 これを気にする必要のないSorpigalの答えも参照してください

sorpigal picture
2012年07月09日
119

ファイルの各行をbash配列に読み込む最も簡単な方法は、次のとおりです。

IFS=$'\n' read -d '' -r -a lines < /etc/passwd

次に、配列linesにインデックスを付けて、各行を取得します。

printf "line 1: %s\n" "${lines[0]}"
printf "line 5: %s\n" "${lines[4]}"

# all lines
echo "${lines[@]}"
Karanjot picture
2013年10月21日
24

ファイルにスペースのない文字列が含まれ、各行に1文字列がある場合の1つの代替方法:

fileItemString=$(cat  filename |tr "\n" " ")

fileItemArray=($fileItemString)

小切手:

配列全体を印刷します。

${fileItemArray[*]}

Length=${#fileItemArray[@]}
Atttacat picture
2015年05月30日
18

あなたの最初の試みは間近でした。 これがあなたのアイデアを使った単純なアプローチです。

file="somefileondisk"
lines=`cat $file`
for line in $lines; do
        echo "$line"
done
Gopesh Bharadwaj picture
2014年04月19日
5
#!/bin/bash
IFS=$'\n' read  -d'' -r -a inlines  < testinput
IFS=$'\n' read  -d'' -r -a  outlines < testoutput
counter=0
cat testinput | while read line; 
do
    echo "$((${inlines[$counter]}-${outlines[$counter]}))"
    counter=$(($counter+1))
done
# OR Do like this
counter=0
readarray a < testinput
readarray b < testoutput
cat testinput | while read myline; 
do
    echo value is: $((${a[$counter]}-${b[$counter]}))
    counter=$(($counter+1))
done