Bashで可変数の変数を読み取る方法

Bashで可変数の変数を読み取る方法

コマンドラインから複数の文字列を読み、トイレのすべての文字列を読みたいです。ループでさらに処理(印刷など)する方法です。申し訳ありません。初心者です。初心者の質問についてご了承ください。

#!/usr/bin/bash


echo "Enter the number of names of students"
read classcount

for ((i=1;i<=classcount;i++)); do
    read names[${i}]
done

for ((i=1;i<=classcount;i++)); do
    echo $names[${i}]
done

ベストアンサー1

通常、スクリプトまたはコマンドラインで使用されるユーティリティでのユーザー対話を避けるのが最善です。自動化を妨げる可能性があるからです。

たとえば、を呼び出すと、削除したいファイルの数を尋ねられ、各ファイルに対して個別にメッセージが表示されることを期待しないrm file1 file2 'file 3'でください。rm

繰り返しますが、ここに記載することをお勧めします学生コマンドラインパラメータから:

#! /usr/bin/bash -
classcount=$#
names=("$@")

if (( classcount > 0 )); then
  echo "Student${name[1]+s}:"
  printf ' - %s\n' "${name[@]}"
fi

次のように呼び出されます。

that-script 'John Doe' 'Alice Smith' ...

または、テキストファイルから1行に1つずつ学生のリストを取得します(GNUと仮定xargs)。

xargs -d '\n' -a student.list that-script

標準入力から各行を読み取ることもできますが、最初に数を求めるのではなく、対話なしで対話し、入力が終わるまでリストを読むことをお勧めします。

#! /usr/bin/bash -

readarray -t names
classcount="${#names[@]}"

if (( classcount > 0 )); then
  echo "Student${name[1]+s}:"
  printf ' - %s\n' "${name[@]}"
fi

stdinが端末の場合、ユーザーは入力の終わりを示すために使用されますCtrl+D

ファイルからリストを取得するには:

that-script < student.list

readstdinから1行を読み取るために使用できますが、構文はIFS= read -r lvalueisではありませんread lvalue

また、これは[...]ワイルドカードなので、リストのコンテキストに表示されるすべてのパラメータ拡張のように引用する必要があります。

また、配列インデックス(Bourne配列を除く"$@")は、bashinと同様にksh(しかし他のほとんどのシェルとは異なり)1ではなく0から始まります。

したがって、あなたの方法の構文は次のとおりです。

#! /usr/bin/bash -
PROGNAME=$0
die() {
  (( $# == 0 )) || printf >&2 '%s: ERROR: %s\n' "$PROGNAME" "$1"
  exit 1
}

IFS= read -rp "Enter the number of names of students: " classcount || die

# validate to avoid command injection vulnerability
shopt -s extglob # only needed in older versions of bash
[[ $classcount = @(0|[123456789]*([0123456789])) ]] ||
  die "Not a valid decimal integer number: $classcount"

for (( i = 1; i <= classcount; i++ )); do
  IFS= read -rp "Student $i: " 'names[i-1]' ||
    die "$(( classcount - i + 1 )) students missing"
done

for (( i=1; i <= classcount; i++)); do
  printf 'Student %s: %s\n' "$i" "${names[i-1]}"
done

$name[$i](t)csh(1970年代後半に配列が最初に導入されたシェル)で動作しますが、コピーの配列設計である$name[$i]:qzshでスペースやワイルドカードが特に処理されないようにする必要があります。bashksh

この点に関して、ksh は Bourne シェルと逆互換性を持っているので、Bourne シェルと同様に、パターンと一致するecho $name[$i]ファイルのリストが出力<contents-of-$name>[<contents-of-$i>]$nameおよび分割)されます。$i

ksh / bashには構文が必要です${name[i]}${name[$i]}またはそれも機能します)、すべてのパラメータ拡張と同様に、分割+globを避けるために${name[${i}]}引用符で囲む必要があります。"${name[i]}"

いずれにせよ、echo任意のデータの出力には使用できません。

おすすめ記事