서브셸에서 명령을 실행하지 않고 명령 출력을 변수에 할당하려면 어떻게 해야 합니까?

서브셸에서 명령을 실행하지 않고 명령 출력을 변수에 할당하려면 어떻게 해야 합니까?

다음과 같은 기능이 있는 경우:

TEST()
{
    if [[ "$1" == "hi" ]]
    then
        exit 1
    fi

    echo "Some text"
}

현재 쉘에서 이 함수를 실행하면:

TEST "hi"

모든 것이 예상대로 작동합니다. 함수의 if 문이 true가 되고 전체 스크립트가 종료됩니다. 반면에 내가 그렇게 한다면:

FUNCTION_OUTPUT=$(TEST "hi")

이 방법으로 변수의 함수에서 stdout을 캡처할 수 있습니다. 함수 내의 if 문은 여전히 ​​true이고 "exit 1"은 계속 실행되지만 하위 쉘에서 실행 중이므로 스크립트는 계속 실행됩니다.

VAR_NAME=$()을 사용하여 하위 쉘에서 무언가를 실행하고 변수에 할당하는 대신 내 함수의 "exit 1" 줄이 실제로 전체 스크립트를 종료하도록 현재 쉘에서 이것을 실행할 수 있는 방법이 있습니까?

답변1

변수 할당은 단지간단한 명령, 그래서 당신은 사용할 수 있습니다if 조건함수가 성공했는지 실패했는지 확인하세요.

if ! FUNCTION_OUTPUT=$(TEST hi); then
  echo Function return non-zero status
  exit 1
fi

# This line never printed
printf '%s\n' "$FUNCTION_OUTPUT"

함수가 성공하면 FUNCTION_OUTPUT함수 결과가 포함된 변수를 얻게 됩니다.

if ! FUNCTION_OUTPUT=$(TEST hii); then
  echo Function return non-zero status
  exit 1
fi

# Output content of FUNCTION_OUTPUT
printf '%s\n' "$FUNCTION_OUTPUT"

답변2

명령을 파일로 리디렉션하고 내장 명령을 사용하여 파일을 변수로 읽어옵니다(예: mapfile.

답변3

스크립트를 종료하는 방법에는 여러 가지가 있습니다.

VAR=$(FUNCTION) || kill -"$(($?&127))" 0

...한 가지 방법일 수도 있습니다. 반환된 내용은 무엇이든 상위 쉘의 프로세스 그룹으로 전달되어야 합니다 FUNCTION. 실제로 구체화되지는 않았지만 원하는 경우 명령 대체에서 쉽게 반환을 얻을 수 있습니다. 또한 현재 쉘 함수 내에서 변수 할당에 대한 조언이 필요한 경우 다음을 수행할 수 있습니다.

fn(){ var=x; }; fn; echo "$var"

x

일부 명령의 출력이어야 한다면 계층적 평가에 대해 이야기하고 있는 것입니다. 실제로 해당 출력을 신뢰해야 합니다. 그렇지 않으면 전체 스트림을 캡처해야 합니다. 이 경우 해당 출력을 언제 받을 수 있는지 확인하는 것이 좋습니다. 이러한 작업은 일반적으로 파이프를 통해 수행됩니다. 이것이 명령 대체가 작동하는 방식이며 물론 하위 쉘도 마찬가지입니다. 쉘과 마찬가지로 read다른 곳에서 제안한 대로 데이터를 입력해야 합니다.

나는 나만의 작은 파이프를 사용하는 것을 좋아합니다. 파이프의 버퍼에 한 번에 조금씩 쓰고 준비가 되면 다시 읽습니다.

fn(){ echo hey; read hey; } <> <(:) >&0
fn; echo "$hey"

hey

...마지막 예를 따를 경우 특히 주의해야 한다고 언급해야 할 것 같습니다.아니요버퍼를 채우려면. 한 번에 조금씩 쓰고 가능한 한 빨리 읽으십시오. 거의 모든 시스템에서 512바이트(많지는 않음)의 기본 버퍼를 사용할 수 있지만 일반적으로 더 큽니다.

주의하지 않으면 해당 파이프의 양쪽 끝 소유자로서 쉘이 교착 상태에 빠졌을 때 다른 프로세스로부터 좌절된 종료 신호를 받지 못하고 영원히 정체될 것입니다. 필요에 따라 파이프를 비우기 위해 리더 프로세스를 분기하지 않는 한, 내장되지 않은 명령의 출력을 이러한 파일 설명자 중 하나에 지정하지 않습니다.

이는 동일한 프로세스 메시징을 어렵게 만듭니다. 완벽한 동기화를 통해 신중하게 관리하고 동시에 작업의 모든 개별 스레드를 추적해야 합니다. 이것이 쉘 포크가 발생하는 이유입니다.

답변4

나는 사용한다:

tmp_fifo=$(mktemp)
mkfifo ${tmp_fifo}
exec 5<>${tmp_fifo}

assign() {
  local var=$1;
  shift
  "$@" >&5
  read ${var} <&5
}

assign myVar echo hola
echo $myVar

rm -f ${tmp_fifo}

관련 정보