次のようにすると、my_command
の出力が行の配列にグループ化されます。
IFS='\n' array_of_lines=$(my_command);
そのため、$array_of_lines[1]
はmy_command
の出力の最初の行を参照し、2番目の行は$array_of_lines[2]
を参照します。
ただし、上記のコマンドはうまく機能しないようです。また、my_command
の出力を文字n
で分割しているようです。print -l $array_of_lines
で確認したところ、配列の要素が1行ずつ出力されると思います。私もこれをチェックしました:
echo $array_of_lines[1]
echo $array_of_lines[2]
...
2回目の試みでは、eval
を追加すると役立つと思いました。
IFS='\n' array_of_lines=$(eval my_command);
しかし、私はそれがない場合とまったく同じ結果を得ました。
最後に、 zshにスペースのある要素をリスト の回答に従って、IFS
の代わりにパラメーター拡張フラグを使用して、zshに入力を分割して要素を収集する方法を伝えました配列、すなわち:
array_of_lines=("${(@f)$(my_command)}");
しかし、同じ結果が得られました(n
で分割が発生しています)
これにより、次の質問があります。
Q1。の出力を収集する「適切な」方法とは行の配列のコマンド?
Q2。改行でのみ分割するIFS
を指定するにはどうすればよいですか?
Q3。上記の3番目の試行のように(つまり、@f
を使用して)パラメータ拡張フラグを使用して分割を指定した場合、zshはIFS
の値?上記でうまくいかなかったのはなぜですか?
TL、DR:
_array_of_lines=("${(@f)$(my_command)}")
_
最初の間違い(→Q2):_IFS='\n'
_はIFS
を_\
_とn
の2文字に設定します。 IFS
を改行に設定するには、_IFS=$'\n'
_を使用します。
2番目の間違い:変数を配列値に設定するには、要素を括弧で囲む必要があります:array_of_lines=(foo bar)
。
空の行を削除することを除いて、これは機能します。連続する空白は単一のセパレータとしてカウントされるためです。
_IFS=$'\n' array_of_lines=($(my_command))
_
IFS
の空白文字を2倍にすると、最後の行を除いて空の行を保持できます。
_IFS=$'\n\n' array_of_lines=($(my_command))
_
空行も追跡し続けるには、コマンドの出力に何かを追加する必要があります。これは、構文解析ではなく、コマンド置換自体で行われるためです。
_IFS=$'\n\n' array_of_lines=($(my_command; echo .)); unset 'array_of_lines[-1]'
_
(_my_command
_の出力が区切り文字のない行で終わっていないと仮定します。また、_my_command
_の終了ステータスを失うことに注意してください)
上記のすべてのスニペットはIFS
をデフォルト以外の値のままにするため、後続のコードが混乱する可能性があることに注意してください。 IFS
localの設定を維持するには、IFS
localを宣言する関数にすべてを入れます(ここでもコマンドの終了ステータスの保持に注意しています)。
_collect_lines() {
local IFS=$'\n\n' ret
array_of_lines=($("$@"; ret=$?; echo .; exit $ret))
ret=$?
unset 'array_of_lines[-1]'
return $ret
}
collect_lines my_command
_
しかし、私はIFS
をいじらないことをお勧めします。代わりに、f
拡張フラグを使用して改行で分割します(→Q1):
_array_of_lines=("${(@f)$(my_command)}")
_
または、末尾の空行を保持するには:
_array_of_lines=("${(@f)$(my_command; echo .)}")
unset 'array_of_lines[-1]'
_
IFS
の値は関係ありません。テストでIFS
を分割して_$array_of_lines
_を出力するコマンドを使用したと思います(→Q3)。
2つの問題:最初に、明らかに二重引用符はバックスラッシュエスケープを解釈しません(それについて申し訳ありません:)。 $'...'
引用符を使用します。そしてman zshparam
によれば、配列内の単語を収集するには、それらを括弧で囲む必要があります。したがって、これは機能します:
% touch 'a b' c d 'e f'
% IFS=$'\n' arr=($(ls)); print -l $arr
a b
c
d
e f
% print $arr[1]
a b
Q3にはお答えできません。私はそのような難解なことを決して知る必要がないことを願っています:)。
Trを使用して、改行をスペースに置き換えることもできます。
lines=($(mycommand | tr '\n' ' '))
select line in lines; do
echo $line
break
done