ユーザー入力で配列値を読み取ると、配列の長さが正しくなく、-aまたは-pのみが読み取りに機能します。

ユーザー入力で配列値を読み取ると、配列の長さが正しくなく、-aまたは-pのみが読み取りに機能します。

Q1:実行時にユーザー入力として配列項目を取得し、項目を印刷し、配列の長さを印刷したいと思います。これが私が持っているものです:

read -a myarray
echo "array items" ${myarray[@]}
echo "array length" ${#myarray[@]}

実行中に、以下を入力として提供しました。

$ ("apple fruit" "orange" "grapes")

出力は、

array items "apple fruit" "orange" "grapes"
array length 4

これは正確ではありません。

ユーザー入力を要求せずにコードの一部として宣言され、初期化された配列を使用すると、配列のmyarray=("apple fruit" "orange" "grapes")長さは3にエコーされます。だから読み取りコマンドを誤って使用しているようです。

質問2:以下のように読み取りコマンドにプロンプ​​トを追加すると、

read -p "enter array items: " myarray

最初のアイテム「リンゴの果実」が「果物」として印刷され、長さも間違っています。

プロンプトを削除して-aを追加すると、すべてが正常です。 aとpを組み合わせてread -apと指定すると、プロンプトはまったく表示されません。値を待ちますが、メッセージはありません。なぜですか?誰かが私に何が間違っているかを説明できますか?

答え1

質問1:

あなたの例では、read入力はコマンドライン引数ではなく標準入力から取得されます。したがって、受信した入力はbash文字列パーサーを通過しません。代わりに、スペースで区切られたリテラル文字列として扱われます。したがって、入力に応じて配列値は次のようになります。

[0]->("apple
[1]->fruit"
[2]->"orange"
[3]->"grapes"

必要な操作を実行するには、区切り文字が適用されないようにすべてのスペースをエスケープする必要があります。つまり、呼び出し後に次のように入力する必要がありますread

apple\ fruit oranges grapes

readQ2:受信した入力を配列として保存するには、-aスイッチの後に配列名を付ける必要があります。したがって、以下が必要です。

read -a myarray -p "Enter your items"

答え2

シェルのコマンドラインパーサーは二重引用符と一重引用符に興味がありますが、そうではありませんread(したがって、どちらも削除しません)。入力するにはreadバックスラッシュが必要です。

apple\ fruit orange grapes

答え3

ユーザーが要素を区切るためにシェル引用符を使用するようにするには、backslashzshのようにします。

IFS= read -r 'string?Please enter the elements: '
array=("${(@XQ)${(z)string}}")
  • (z)$stringこれはシェルパーサなどの要素に分割されます。
  • Q結果の単語から最初のレベル参照を削除します。
  • X構文によるエラーメッセージの報告
  • @空の要素を保存するには、引用符を使用してください。

このようにして、ユーザーは次のように入力できます。

'first word' "second word" third\ word $'word\nwith\nnewline' ''

拡張が行われなくても、予想されるシェルコード構文は引用符に限定されません。たとえば、単一の単語$(foo bar)に解析され、構文エラーが発生します。ユーザーはこれを、または「${unknown」と入力する必要があります。$(foo bar)${unclosed'$(foo)' 'bar)'

関連情報