web-dev-qa-db-ja.com

改行によりサブシェルからzsh配列を分割

サブシェルからzsh配列をインスタンス化したい

_myarray=($(somecommand)
_

欲しいものを受け取ったかどうかを確認します

_for element in $myarray ; do echo "===" ; echo $element ; echo "---" ; done
_

デフォルトでは、要素を区切るために空白(スペースと改行)が使用されています。

また、${(s:-:)"$(somecommand)"}を使用して_-_で区切ることができることもわかりました。この場合、スペースと改行は要素を分割しません(つまり、配列要素に改行を含めることができます)。

これまでのところ、改行でのみ分割できません。つまりsomecommandが返す場合

_Alice
Bob
Arthur C Clarke
Neo
Thomas Anderson
_

上記のforループを印刷してください:

_===
Alice
---
===
Bob
---
===
Arthur C Clarke
---
===
Neo
---
===
Thomas Anderson
---
_

どうすればそれを達成できますか? (そして、おそらくそれをマニュアルのどこに参照するかへのポインタ。)

5
pseyfert

ネイティブの分割演算子(引用符で囲まれていないコマンド置換で実行されるBourneのような$IFS Word分割の横)は、sパラメータ展開フラグを使用します。

array=(${(ps:\n:)"$(cmd)"})

cmdの出力を改行で分割し、空の要素(空の行)を破棄します。

pは、これらの\x拡張を有効にするためのものです。 ps:\n:は一般的なものなので、エイリアスは短くなります:f(行で分割するにはf eeds):

array=(${(f)"$(cmd)"})

空の行を保持するには、次のようにします。

array=("${(f@)$(cmd)"})

ここで、他のほとんどのシェルと同様に、コマンド置換はallで後続の改行文字を削除するため、後続のすべての空行が削除されることに注意してください。それらを保存するには、次のようにします。

array=("${(f@)$(cmd; echo .)}")
array[-1]=()  # remove that last line added by echo .

$IFSで単語分割:

IFS=$'\n'
array=($(cmd)) # removes empty lines. Note that contrary to other
               # Bourne-like shells, zsh doesn't do globbing there
               # so you don't need the "set -o noglob"

IFS=$'\n\n' # like in ksh93, doubling an IFS-whitespace character
            # removes its special treatment as a whitespace character
array=($(cmd)) # preserves empty lines except the trailing ones

IFS=$'\n\n'
array=($(cmd; echo .)); array[-1]=() # preserves all empty lines.

$IFSをグローバルに変更しないようにするには、無名関数で上記を実行できます。

(){
  local IFS=$'\n\n'
  array=($(cmd; echo .)); array[-1]=()
}

また、$array展開は空の要素をスキップすることに注意してください。したがって、空の要素を含むall要素をループしたい場合は、次のものが必要です。

for i ("$array[@]") ...

または

for i ("${(@)array}") ...

ない

for i ($array) ...
for i in $array
11