web-dev-qa-db-ja.com

Bashのテキストファイルから配列を作成する

スクリプトはURLを取得し、それを解析して必要なフィールドを探し、その出力をリダイレクトしてファイルfile.txtに保存します。出力は、フィールドが見つかるたびに新しい行に保存されます。

file.txt

A Cat
A Dog
A Mouse 
etc... 

file.txtを取得し、そこから新しいスクリプトで配列を作成します。すべての行は配列内の独自の文字列変数になります。これまで私は試しました:

#!/bin/bash

filename=file.txt
declare -a myArray
myArray=(`cat "$filename"`)

for (( i = 0 ; i < 9 ; i++))
do
  echo "Element [$i]: ${myArray[$i]}"
done

このスクリプトを実行すると、空白の結果、単語が分割され、代わりに

望ましい出力

Element [0]: A Cat 
Element [1]: A Dog 
etc... 

私はこれを得ることになります:

実際の出力

Element [0]: A 
Element [1]: Cat 
Element [2]: A
Element [3]: Dog 
etc... 

各行の文字列全体が配列内の各変数と1対1で対応するように、以下のループを調整するにはどうすればよいですか?

67
user2856414

mapfile コマンドを使用します。

mapfile -t myArray < file.txt

エラーはforを使用しています-ファイルのlinesをループする慣用的な方法は次のとおりです。

while IFS= read -r line; do echo ">>$line<<"; done < file.txt

詳細については、 BashFAQ/005 を参照してください。

79
glenn jackman

mapfileおよびreadarray(同義)は、Bashバージョン4以降で使用できます。 Bashの古いバージョンを使用している場合、ループを使用してファイルを配列に読み込むことができます。

arr=()
while IFS= read -r line; do
  arr+=("$line")
done < file

ファイルの最後の行が不完全(改行がない)の場合、次の代替手段を使用できます。

arr=()
while IFS= read -r line || [[ "$line" ]]  do
  arr+=("$line")
done < file

関連する:

13
codeforester

これもできます:

oldIFS="$IFS"
IFS=$'\n' arr=($(<file))
IFS="$oldIFS"
echo "${arr[1]}" # It will print `A Dog`.

注意:

ファイル名の展開は引き続き発生します。たとえば、リテラル*を持つ行がある場合、現在のフォルダー内のすべてのファイルに展開されます。したがって、ファイルにこの種のシナリオがない場合にのみ使用してください。

7
Jahid

ファイルから各行を読み取り、それを配列に割り当てるだけです。

#!/bin/bash
i=0
while read line 
do
        arr[$i]="$line"
        i=$((i+1))
done < file.txt
4
Prateek Joshi

Mapfileを使用するか、-aを読み取ります

常に shellcheck を使用してコードを確認してください。多くの場合、正しい答えが得られます。この場合、 SC2207 は、スペースで区切られた値または改行で区切られた値を持つファイルを配列に読み込むことをカバーします。

これをしないでください

array=( $(mycommand) )

改行で区切られた値を持つファイル

mapfile -t array < <(mycommand)

スペースで区切られた値を持つファイル

IFS=" " read -r -a array <<< "$(mycommand)"

Shellcheckページには、これがベストプラクティスと見なされる理由が示されています。

この回答 は使用するように言っています

mapfile -t myArray < file.txt

何らかの理由でbash <4.xでmapfileを使用する場合は、mapfileに対して shim を作成しました。 bash> = 4.xを使用している場合は、既存のmapfileコマンドを使用します

現在、オプション-dおよび-tのみが機能します。ただし、上記のコマンドにはこれで十分です。 macOSでのみテストしました。 macOS Sierra 10.12.6では、システムbashは3.2.57(1)-releaseです。そのため、シムが役立ちます。 bashをhomebrewで更新したり、bashを自分でビルドしたりすることもできます。

この手法 を使用して、変数を1つの呼び出しスタックに設定します。

1
dosentmatter