パイプに追加すると、これらの値が正しく追加されないのはなぜですか? [コピー]

パイプに追加すると、これらの値が正しく追加されないのはなぜですか? [コピー]

私はbashスクリプトを持っています(参照ここ)サブディレクトリにあるファイルのリストをファイル名でソートするために使用します。

スクリプトはソートされたファイルをに追加し、hooks/pre-relevant/ファイルを追加します。名前付き hooks/pre-relevant、名前付きファイルを順番に選択し、hooks/relevant次の関数をhooks/relevant/使用してappend_hookファイルを並べ替えます。

hooks=()

# Run a hook script, if it's executable, with the input from this invocation
append_hook () {
  if [[ -f "$1" && -x "$1" ]]; then
    hooks+=("$1")
  fi
}

次のディレクトリ構造を使用してテストしています。

testing-range/plugins/
|-- bar
|   `-- hooks
|       |-- irrelevant
|       |-- only-one
|       `-- relevant
|-- dickory
|   `-- hooks
|       `-- pre-relevant
|-- doc
|   `-- hooks
|       |-- perl-envsubst
|       `-- relevant
|           |-- 00
|           `-- 20
|
|-- factory
|   `-- hooks
|       `-- relevant
`-- hickory
    `-- hooks
        |-- pre-relevant
        |   `-- 30
        `-- relevant
            `-- 10

このマルチレベル配列コードを使用してファイルを添付すると、次のようになります。

append_numbered_hooks () {
  # Gather every file into an array, prefixing each item with the
  # filename of the script (its position in sort order)
  local filelist=()
  for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$hookname"/*; do
    filelist+=("${hook##*/}/$hook")
  done

  # Sort the array numerically
  printf '%s\0' "${filelist[@]}" | sort -nz | IFS= read -rd '' -a filelist

  # Append each script in sorted order
  for hookline in "${filelist[@]}"; do
    append_hook "${hookline#*/}"
  done
}

わかりました。ほぼ正しい出力:

hickory/hooks/pre-relevant/30
dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant
doc/hooks/relevant/00
doc/hooks/relevant/20
hickory/hooks/relevant/10

ただし、この単純なパイプを使用してファイルを追加すると、次のようになります。

append_numbered_hooks () {
  for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$1"/*; do
    printf '%s\0' "${hook##*/}/$hook"
  done | sort -nz | while IFS= read -rd '' hookline; do
    append_hook "${hookline#*/}"
  done
}

番号付きファイルは、「${hooks[@]}」ループには表示されません。

dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant

どうなりますか?正しい値は次のとおりです。

hickory/hooks/pre-relevant/30
dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant
doc/hooks/relevant/00
hickory/hooks/relevant/10
doc/hooks/relevant/20

答え1

~からhttp://www.gnu.org/software/bash/manual/bashref.html#Pipelines

パイプラインの各コマンドは、独自のサブシェルで実行されます。

したがって、サブシェルで変数を変更しています。これらの変更は、サブシェルが終了すると消えます。

あなたは見つけることができますプロセスの交換役に立つ。

append_numbered_hooks () {
  while IFS= read -rd '' hookline; do
    append_hook "${hookline#*/}"
  done < <(
    for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$1"/*; do
      printf '%s\0' "${hook##*/}/$hook"
    done | 
    sort -nz
  )
}

関連情報