改行でサブシェルからzsh配列を分割する

改行でサブシェルから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
---

どうやってこれを達成できますか? (マニュアルでこのコンテンツが見つかる場所を示すこともできます。)

ベストアンサー1

デフォルトの分割演算子($IFS引用符なしのコマンド置換で実行されるBourneなどの単語分割に加えて)は、パラメータs拡張フラグを使用します。

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

cmd出力は空の要素(空行)を破棄して改行に分割されます。

pこれらの\x拡張を有効にすることです。いつものように、ps:\n:エイリアスは短いです:(fオンライン分割F種子):

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

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

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

他のほとんどのシェルと同様に、コマンドの代替バーがみんな末尾の改行文字なので、すべての末尾の空白行です。これを保存するには、次のようにします。

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拡張は空の要素をスキップします。したがって、ループが必要な場合みんな空の要素を含む要素の場合は、次のことを行う必要があります。

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

または

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

いいえ

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

おすすめ記事