해결됨:

해결됨:

환경 변수를 설정하는 다음과 같은 재귀 함수가 있습니다.

function par_set {
  PAR=$1
  VAL=$2
  if [ "" != "$1" ]
  then
    export ${PAR}=${VAL}
    echo ${PAR}=${VAL}
    shift
    shift
    par_set $*
  fi
}

단독으로 호출하면 변수가 설정되고 stdout으로 에코됩니다.

$ par_set FN WORKS
FN=WORKS
$ echo "FN = "$FN
FN = WORKS

stdout을 파일로 리디렉션하는 것도 가능합니다.

$ par_set REDIR WORKS > out
cat out
REDIR=WORKS
$ echo "REDIR = "$REDIR
REDIR = WORKS

그러나 stdout을 다른 명령으로 파이프하면 변수가 설정되지 않습니다.

$ par_set PIPE FAILS |sed -e's/FAILS/BARFS/'
PIPE=BARFS
$ echo "PIPE = "$PIPE
PIPE =

파이프가 함수가 변수를 내보내는 것을 방지하는 이유는 무엇입니까? 임시 파일이나 명명된 파이프를 사용하지 않고 이 문제를 해결할 수 있는 방법이 있습니까?

해결됨:

작업 코드를 제공해 주신 Gilles에게 감사드립니다.

par_set $(echo $*|tr '=' ' ') > >(sed -e's/^/  /' >> ${LOG})

이를 통해 스크립트를 다음과 같이 호출할 수 있습니다.

$ . ./script.sh PROCESS_SUB ROCKS PIPELINES=NOGOOD
$ echo $PROCESS_SUB
ROCKS
$ echo $PIPELINES
NOGOOD
$ cat log
7:20140606155622162731431:script.sh:29581:Parse Command Line parameters.  Params must be in matched pairs separated by one or more '=' or ' '.
  PROCESS_SUB=ROCKS
  PIPELINES=NOGOOD

Bitbucket에서 호스팅되는 프로젝트https://bitbucket.org/adalby/monitor-bash전체 코드에 관심이 있는 경우.

답변1

파이프의 각 부분(즉, 파이프의 각 측면)은 별도의 프로세스(서브쉘이라고 함)에서 실행됩니다.포크스크립트의 일부를 실행하는 하위 프로세스). 에서는 실행 파이프라인 왼쪽에 있는 하위 프로세스에 변수가 설정됩니다 par_set PIPE FAILS |sed -e's/FAILS/BARFS/'. PIPE이 변경 사항은 상위 프로세스에 반영되지 않습니다. 환경 변수는 프로세스 간에 전달되지 않으며 하위 프로세스에서만 상속됩니다.

파이프의 왼쪽은 항상 하위 쉘에서 실행됩니다. 일부 쉘(ATT ksh, zsh)은 상위 쉘에서 오른쪽을 실행하며 대부분은 하위 쉘에서도 오른쪽을 실행합니다.

스크립트 일부의 출력을 리디렉션하고 상위 셸에서 해당 부분을 실행하려면 ksh/bash/zsh에서 다음을 사용할 수 있습니다.프로세스 교체.

par_set PROCESS SUBSTITUTION > >(sed s/ION/ED/)

POSIX 셸을 사용하면 출력을 명명된 파이프로 리디렉션할 수 있습니다.

mkfifo f
<f grep NAMED= &
par_set NAMED PIPE >f

아, 그리고 넌 없어졌어변수 대체에 대한 인용문, 귀하의 코드는 다음과 같은 문제로 인해 중단됩니다 par_set name 'value with spaces' star '*'.

export "${PAR}=${VAL}"
par_set "$@"

답변2

파이프의 각 끝이 의 하위 쉘에서 실행되고 bash하위 쉘에 설정된 변수가 해당 하위 쉘에 로컬이기 때문에 이는 작동하지 않습니다.

고쳐 쓰다:

부모 쉘에서 자식 쉘로 변수를 전달하는 것은 쉬운 것 같지만진짜다른 방법으로는 어렵네요. 일부 해결 방법에는 명명된 파이프, 임시 파일, stdout에 쓰기 및 상위에서 읽기 등이 있습니다.

일부 참고자료:

http://mywiki.wooledge.org/BashFAQ/024
https://stackoverflow.com/q/15541321/3565972
https://stackoverflow.com/a/15383353/3565972
http://forums.opensuse.org/showthread.php/458979-How-export-variable-in-subshell-back-out-to-parent

답변3

파이프 외부 쉘에서 약간의 속임수로 해결할 수 있는 하위 쉘을 지적했지만 문제의 더 어려운 부분은 파이프의동시성.

파이프의 모든 프로세스 멤버는 다음으로 시작합니다.한 번, 따라서 다음과 같이 문제를 살펴보면 이해하기가 더 쉬울 수 있습니다.

{ sleep 1 ; echo $((f=1+2)) >&2 ; } | echo $((f))
###OUTPUT
0
...
3

파이프라인 프로세스는 변수가 설정되기 전에 닫혀 실행되기 때문에 변수 값을 상속받을 수 없습니다.

나는 당신의 기능의 요점이 무엇인지 정말로 이해할 수 없습니다. 아직 어떤 목적을 가지고 있습니까 export? 아니면 그냥 var=val? 예를 들어, 여기거의다시 동일한 파이프라인:

pipeline() { 
    { sleep 1
      echo "f=$((f=f+1+2))" >&3
    } | echo $((f)) >&2
} 3>&1

f=4 pipeline

###OUTPUT

4
...
f=7

그리고 export:

export $(f=4 pipeline) ; pipeline

###OUTPUT:

4
7
...
f=10

따라서 귀하의 작업은 다음과 같이 작동할 수 있습니다.

par_set $(echo PIPE FAILS | 
    sed 's/FAIL/WORK/;/./w /path/to/log')

sed출력을 파일에 기록 하고 이를 shell-split 로 함수에 전달합니다 "$@".

또는 다른 옵션:

$ export $(echo PIPE FAILS | sed 's/ FAIL/=WORK/')
$ par_set $PIPE TWICE_REMOVED
$ echo "WORKS = "$WORKS
WORKS = TWICE_REMOVED

그러나 귀하의 함수를 작성한다면 다음과 같을 것입니다.

_env_eval() { 
    while ${2+:} false ; do
       ${1:+export} ${1%%["${IFS}"]*}="${2}" || :
       shift 2
    done
}

관련 정보