조건부 프로세스 교체

조건부 프로세스 교체

여러 매개변수가 포함된 명령이 있습니다.

my_command --arg1 <arg1> \
    --arg2 <arg2> \
    --arg3 <arg3>

my_command전달될 수도 있고 전달되지 않을 수도 있는 다양한 매개변수의 값을 설정하는 함수로 호출을 래핑합니다 .

run_my_command() {
    if [[ ... ]]; then
        ARG1FLAGS="--arg1 $ARG1"
    else
        ARG1FLAGS=''
    fi
    if [[ ... ]]; then
        ARG2FLAGS="--arg2 $ARG2"
    else
        ARG2FLAGS=''
    fi
    if [[ ... ]]; then
        ARG3FLAGS="--arg3 $ARG3"
    else
        ARG3FLAGS=''
    fi

    my_command $ARG1FLAGS \
        $ARG2FLAGS \
        $ARG3FLAGS
}

어떤 경우에는 파일 이름 인수를 다음으로 전달해야 합니다 my_command.

run_my_command() {
    # ...
    if [[ ... ]]; then
        FILEARG="--input_file $SOME_FILE"
    else
        FILEARG=''
    fi

    my_command $FILEARG \
        ...
}

이 모든 것이 잘 작동합니다. 이제 조건부로 프로세스 대체를 사용하고 싶지만 FILEARG당연히 작동하지 않습니다.

run_my_command() {
    # ...
    if [[ ... ]]; then
        FILEFLAG='--input_file'
        FILEARG=<(other_cmd)
    else
        FILEARG=''
    fi

    my_command $FILEFLAG $FILEARG \
        ...
}

런타임에 의해 my_command익명 $FILEARG파이프처럼 보이는 것이 /dev/fd/63닫혔기 때문입니다.

이제 모든 것을 조건부로 넣어 my_command이 문제를 해결했습니다 .

run_my_command() {
    # Get ARG1, ARG2, ARG3...
    if [[ ... ]]; then
        my_command --input_file <(other_cmd) \
            $ARG1FLAGS \
            $ARG2FLAGS \
            $ARG3FLAGS
    else
        my_command $ARG1FLAGS \
            $ARG2FLAGS \
            $ARG3FLAGS
    fi
}

하지만 나는 반복을 좋아하지 않는다. 를 사용하여 뭔가를 할 수 있거나 다른 함수 eval에 넣을 수 있을 것 같지만 my_command아직 파악하지 못했습니다.my_command전체 호출을 복제하지 않고 읽을 수 있는 파일을 생성하기 위해 조건부로 프로세스 대체를 사용하려면 어떻게 해야 합니까 my_command?

나는 bash 4.4.19를 실행하고 있습니다. 놀랍게도 bash 3.2.57은 아래 Bash Hackers 위키에서 제안한 방식으로 작동하는 것 같습니다.

doit() {
    local -r FOO=<(echo hi)
    cat $FOO
}

doit

# bash 3.2.57:
$ ./test.sh
hi
# bash 4.4.19:
$ ./test.sh
cat: /dev/fd/63: Bad file descriptor

다음은 제가 확인한 몇 가지 질문이지만 다음으로부터 유효한 답변을 얻을 수 없습니다.

게다가,배쉬 해커 위키 노트오히려 신비롭게:

프로세스 대체가 함수에 대한 인수, 함수 호출 중 환경 변수 또는 함수 내의 할당으로 확장되면 프로세스 대체는 함수 내에서 또는 호출되는 모든 명령에서 사용할 수 있도록 "열린 상태로 유지"됩니다. 또는 이를 설정한 함수가 반환될 때까지. 호출 수신자에서 동일한 변수가 다시 설정되면 새 변수가 로컬이 아닌 한 이전 프로세스 대체가 해제되고 호출 수신자가 반환될 때 호출자가 변수를 사용할 수 없습니다.

기본적으로 함수 내 변수로 확장되는 프로세스 대체는 프로세스 대체가 발생하는 함수가 반환될 때까지 켜져 있습니다. 이는 함수 호출자가 설정한 지역 변수에 할당된 경우에도 마찬가지입니다. 동적 범위는 닫히는 것을 방지하지 않습니다.

그러나 함수의 변수에 프로세스 대체를 할당하는 것만으로는 "열린 상태를 유지할" 수 없습니다.

답변1

이는 질문을 하는 것과 비슷하지만 다른 매개변수를 단일 변수가 아닌 배열에 넣으면 중복이 줄어듭니다.$ARGnFLAGS

어떤 경우든, 이는 단어 분할이나 파일 이름 글로빙을 방해하지 않고 명령에 대한 인수를 얻을 수 있기 때문에 옳은 일이기도 합니다.

run_my_command() {
    args=()
    if [[ ... ]]; then
        args+=(--arg1 "$ARG1")
    fi
    if [[ ... ]]; then
        args+=(--arg2 "$ARG2")
    fi

    if [[ ... ]]; then
        my_command --input_file <(other_cmd) "${args[@]}"
    else
        my_command "${args[@]}" 
    fi
}

답변2

run_my_command() {
    # ...
    if [[ ... ]]; then
        tmpfile=$(mktemp)
        trap 'rm -f "$tmpfile"' RETURN
        other_cmd >"$tmpfile"
        FILEFLAG='--input_file'
        FILEARG="$tmpfile"
    else
        FILEARG=''
    fi

    my_command $FILEFLAG $FILEARG \
        ...

    return
}

...또는 그런 것.

즉, 프로세스 교체를 사용하는 대신 임시 파일을 사용하십시오.

답변3

다음 방법을 사용하여 eval원하는 것을 얻을 수 있습니다.

run_my_command() {
    # Get ARG1, ARG2, ARG3...
    commandline="my_command $ARG1FLAGS $ARG2FLAGS $ARG3FLAGS"
    if [[ ... ]]; then
        commandline="$commandline --input_file <(other_cmd)"
    fi
    eval $commandline
}

관련 정보