IFS ループを使用してファイルを読み込むことは、配列を使用しない場合にのみ機能します。

IFS ループを使用してファイルを読み込むことは、配列を使用しない場合にのみ機能します。

次のコードを使用してファイルを配列に読み込もうとしています。

GROUPS=()

while IFS=: read -r g1 g2 g3 g4
do
    GROUPS+=("$g3")
    echo "$g3"
done < /etc/group

これは動作せず、何も出力しません。ただし、エコーをそのままにするとファイルの内容が印刷されます。配列に追加するコマンドがループのどこかで発生する限り、何も印刷されません。他のファイルでも問題なくこれを行うことができるので、これは奇妙に見えます。

原因は何か知っていますか? bash -xで確認しましたが、問題になるコマンドがあるとループに入ることもありません。

また、関連性がある場合はrootとして実行します。

答え1

bash残念ながら、すでに独自に予約されている配列の名前を選択しました。読み取り専用なので変更できません。

グループ

現在のユーザーが属するグループのリストを含む配列変数。 GROUPS の割り当てが正しくなく、エラー状態が返されます。 GROUPS が設定されていない場合は、後でリセットしても特殊属性が失われます。

別の名前を使用すると、コードが機能します。

答え2

ループを使用してbashでこれを完全に実行する方法に対する答えはすでにありますwhile ... read ...。 bashでのみこれを行うことが最悪の方法の1つであると提案したいと思います。

また、/etc/groupファイルはグループデータの可能なソースの1つにすぎないため、読み込み自体は良い考えではありません。他のソースには、LDAP、Active Directory、winbind、NIS、mysql、pgsql、Berkeley dbファイルなどの追加のグループファイルを含めることができますlibnss-extrausers。もっと)。

代わりに出力を使用してくださいgetent group

この試み:

g=( $(getent group | awk -F: '{print $3}') )

または

g=( $(getent group | cut -d: -f3) )

awkこの方法は、正規表現、固定テキスト検索、および/$1 == groupnameまたは他の選択基準と$3 >= 500 && $3 <= 1000組み合わせたい場合に特に便利です。

たとえば、デバッグのために、次のように配列のグループを印刷できますg

# all on one line
echo "${g[@]}"

# one element per line
printf "%s\n" "${g[@]}"

# in a format that can be re-used to define the variable in another
# bash shell or script.
declare -p g

私は特にdeclare -pデバッグが大好きです。変数名(例:のようなものecho "foo='$foo'")だけでなく、配列変数の配列インデックスも表示され、すべてが適切に引用され、バックスラッシュがエスケープされます。

$ g=( $(getent group | awk -F: '$1 ~ /my/ {print $1}') )
$ declare -p g
declare -a g='([0]="mysql" [1]="mythtv")'

BTWは、bashやkshなどの他のシェルで作業するのと同義ですtypesetdeclare

関連情報