파이프에 추가할 때 이러한 값이 올바르게 추가되지 않는 이유는 무엇입니까? [복사]

파이프에 추가할 때 이러한 값이 올바르게 추가되지 않는 이유는 무엇입니까? [복사]

나는 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
  )
}

관련 정보